# Notice Schema — Layer 3 Specialized Entity Type # KNO Schema Version: 0.1.0 # # A Notice is a structured platform announcement: deprecations, outages, # capability changes, scheduled maintenance, and other situational- # awareness signals partners need to react to. # # EXTENDS: document-schema.kno (which composes identity, history, quality) # # DESIGN DECISIONS: # - DD-NTC-01: One entity, not three subtypes. Per kno-foundational- # principles § 0.6 (Schema Minimization) and P6 (Morphological / # Emergent), platform-MOTD vs. possibility-MOTD vs. usage-MOTD are # inferable from the relationship graph (`applies_to` targets), not # from a discriminator field. Schema-minimization Gate 1 (distinctness) # fails — they share shape; their scope is emergent from XRI links. # - DD-NTC-02: Scope is inferred from `applies_to`. Platform-wide notices # target the well-known XRI `pspace://platform`; possibility-scoped # notices target `pspace://possibility/`; endpoint-scoped notices # target `pspace://api-endpoint/`. # - DD-NTC-03: `body` carries KAML for rich rendering on /status; tools # that only consume structured data can rely on `summary`. # - DD-NTC-04: `visibility: public` on the schema means platform-scoped # and endpoint-scoped instances project onto the four-surface contract # (REST + llms.txt + MCP + A2A) per REQ-18. Per Phase 2 P6 standing # rule, MCP/A2A projection is paused until M54; REST + llms.txt + the # /status page ship in M52. # - DD-NTC-05: `applies_to` ↔ `affected_by` is a bidirectional XRI # predicate pair, mirroring the `documents` ↔ `documented_by` # precedent. CI lint enforces backlink consistency. # # USE CASES: # - Endpoint deprecation notices (paired with B5 Sunset/Deprecation headers) # - Platform outage / maintenance announcements # - Capability lifecycle changes (deprecation, removal, replacement) # - Configuration-required signals (e.g., custom-auth-domain rollout) # # COMPOSES WITH: # - #1956 (B2 remediation middleware) — emits `Link: rel="related-notice"` # on 4xx responses whose endpoint XRI is `affected_by` an active notice # - #1959 (B5 Sunset/Deprecation headers) — same Link header on responses # from deprecated endpoints # ============================================================================= # SCHEMA DECLARATION (RFC-007) # ============================================================================= $schema: kno@0.0.9 # ============================================================================= # IDENTITY (composed from identity-schema.kno) # ============================================================================= id: 01KQ58HMB86E2YMMDCXZ1NMSZJ slug: notice-schema type: spec version: 0.1.1 # ============================================================================= # STANDARD TIER # ============================================================================= title: "Notice Schema" purpose: | Define the schema for Notice entities — structured platform announcements that partners and agents need to consume to react to deprecations, outages, capability changes, and scheduled maintenance. **What is a Notice?** A .kno file declaring a single platform announcement: its severity, status, publication window, body (KAML), and the XRIs it applies to. **Scope is emergent (P6 + P10):** Notices do NOT carry a `scope` discriminator. Their scope is inferred from `applies_to`: | XRI in `applies_to` | Inferred scope | |---------------------------------|--------------------| | `pspace://platform` | Platform-wide | | `pspace://possibility/` | Possibility-scoped | | `pspace://api-endpoint/` | Endpoint-scoped | | `pspace://capability/` | Capability-scoped | **Bidirectional predicates (P7 + P10):** Each XRI in `applies_to` MUST have a reverse `affected_by` link from the target back to this notice, validated by `lint-api-contract-honesty.ts`. Mirrors the established `documents` ↔ `documented_by` precedent in `relationship-vocabulary-schema.kno`. **Visibility (REQ-18):** `visibility: public` for platform-scoped and endpoint-scoped notices — they are reference data partners need. Per Phase 2 P6 standing rule, MCP/A2A projection is paused until M54 ships the messaging layer; REST + llms.txt + the /status page ship in M52. **Why a separate schema (not document-schema with purpose: notice)?** Per kno-foundational-principles § 0.6 (Schema Minimization), this passes the three-gate test: - Gate 1 (Distinctness): Notices are time-bounded structured signals (severity + status + published_at + expires_at + applies_to), not narrative documents. They share shape with capability-schema status fields, not with prose documents. - Gate 2 (Reusability): At least one seed instance at introduction (the 2026-04-25 custom-auth-domain rollout); growable as new deprecation, outage, and capability-change events occur. - Gate 3 (Clarity): Separating notices from documents keeps the middleware projection (`Link: rel="related-notice"`) and the lint backlink check type-driven. # ============================================================================= # RICH TIER — Taxonomy # ============================================================================= provenance: origin: id: 01KQ58HMB86E2YMMDCXZ1NMSZJ timestamp: "2026-04-26T00:00:00Z" tool: manual issue: "PossibilityTruthy/possibility-space#2052" taxonomy: topics: - notice - announcement - deprecation - outage - platform-status - situational-awareness keywords: - notice - motd - deprecation - sunset - status - platform-event # ============================================================================= # RICH TIER — Relationships # ============================================================================= relationships: extends: - xri: "kno://specs/document-schema" reason: "Notice entities inherit identity, history, and quality fields" depends_on: - xri: "kno://specs/kno-spec" reason: "RFC-001 defines kno@0.0.9 schema" - xri: "kno://specs/relationship-vocabulary-schema" reason: "Defines the applies_to / affected_by predicate pair" composes: - xri: "kno://specs/identity-schema" reason: "Layer 1: id, slug" - xri: "kno://specs/history-schema" reason: "Layer 1: _history, changelog" - xri: "kno://specs/quality-schema" reason: "Layer 1: quality, validation, confidence" - xri: "kno://specs/kaml-spec" reason: "Notice body uses KAML markup" related_to: - xri: "kno://specs/api-spec" reason: "Notices may apply_to API endpoints; B2 remediation middleware emits Link: rel=\"related-notice\" composing the two surfaces" - xri: "kno://specs/capability-schema" reason: "Notices may apply_to capabilities (lifecycle change announcements)" - xri: "kno://specs/possibility-schema" reason: "Notices may apply_to possibilities (per-tenant signals; public surface deferred to a future iteration per #2052 scope)" # ============================================================================= # VISIBILITY DECLARATION (REQ-18) # ============================================================================= # Platform-scoped and endpoint-scoped notice instances are public reference # data. Possibility-scoped instances are conceptually authenticated-only; # their public projection is out of scope for M52 per #2052. # # Per Phase 2 P6 standing rule (4-surface announce paused until M54): # - REST: GET /notices, GET /notices/:id — ships in M52 (#2052) # - llms.txt: notices listed in /docs/llms.txt aggregate — ships in M52 # - MCP: notices_search / notices_get tools — DEFERRED to M54 # - A2A: agent-card resource for notices — DEFERRED to M54 visibility: public # ============================================================================= # REQUIRED FIELDS # ============================================================================= fields: # --------------------------------------------------------------------------- # IDENTITY (inherited from document-schema, restated for clarity) # --------------------------------------------------------------------------- id: type: string format: ulid required: true description: "ULID of this Notice (immutable birth identity, RFC-013)" slug: type: string required: true pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9-]+$" description: | Human-readable identifier. MUST follow the `YYYY-MM-DD-{kebab-summary}` pattern so notice files sort chronologically by publication date. Example: `2026-04-25-custom-auth-domain-required`. type: type: string enum: [ notice ] required: true description: "Top-level kind discriminator" version: type: string format: semver required: true description: "Semantic version of this notice instance (bumps when the body or status materially changes)" # NOTE: Per the established codebase convention (every other .kno # entity, including registry-schema, definition-schema, mcp-registry, # def-*), `conforms_to` is declared inside the `relationships:` block # as a structured XRI reference, NOT as a top-level scalar. Notice # instances therefore declare: # relationships: # conforms_to: # - xri: "kno://specs/notice-schema" # reason: "notice-schema v0.1.0" # The schema does not list a top-level `conforms_to` requirement. # --------------------------------------------------------------------------- # NOTICE-SPECIFIC FIELDS # --------------------------------------------------------------------------- name: type: string required: true description: | Display name for this notice. Used as the headline on /status and in notification surfaces. Should be short (≤ 80 chars), capitalized sentence case, and convey the change at a glance. examples: - "Custom auth domain required for production OIDC clients" - "Scheduled maintenance: object storage region failover" summary: type: string required: true description: | One-sentence machine-readable summary. This is the field MCP / A2A surfaces will project (when M54 ships) and the field `Link: rel="related-notice"` consumers will display in tooltips. Plain text only; no markup. examples: - "Production OIDC clients must configure a custom auth domain before invoking /oauth/authorize or /oauth/end-session." body: type: string format: kaml required: true description: | KAML body rendered on /status and on the per-notice REST endpoint. May contain headings, lists, code blocks, and inline links. Should explain: (1) what is changing, (2) who is affected, (3) what action partners need to take, (4) the timeline. severity: type: string enum: [ info, warning, critical ] required: true description: | Severity level for visual treatment on /status and for filtering in `GET /notices?severity=`. - `info` — Informational; no action required. - `warning` — Action required by `expires_at` or recommended before that date to avoid disruption. - `critical` — Immediate action required; service is degraded or will be by `expires_at`. status: type: string enum: [ scheduled, active, resolved ] required: true description: | Lifecycle stage: - `scheduled` — `published_at` is in the future. The notice is discoverable on `/notices?status=scheduled` but does NOT trigger `Link: rel="related-notice"` injection. - `active` — `published_at` is in the past and either `expires_at` is in the future or unset. Triggers Link header injection on matched endpoints. - `resolved` — The condition described by the notice has been remediated, OR `expires_at` is in the past. Visible via `/notices?status=resolved` but does NOT trigger Link headers. published_at: type: string format: date-time required: true description: | ISO-8601 UTC timestamp when this notice becomes / became active. Notices with `published_at` in the future MUST have `status: scheduled`. The notice transitions to `active` when this time is reached (transition is currently manual via `version` bump; an automated transition job is deferred to M54). expires_at: type: string format: date-time required: false description: | ISO-8601 UTC timestamp after which this notice is no longer relevant. Optional — informational notices may be open-ended. When set and in the past, the notice MUST be transitioned to `status: resolved` (manually for now; automated in M54). applies_to: type: array required: true min_items: 1 description: | List of XRIs this notice scopes. Each entry MUST resolve to an entity that declares a reverse `affected_by` edge back to this notice; CI lint (`lint-api-contract-honesty.ts`) enforces this bidirectional consistency. Well-known XRIs: - `pspace://platform` — Platform-wide notices (the entire Possibility platform). The reserved-XRI registry documents this anchor. - `pspace://api-endpoint/` — Endpoint-scoped notices. Triggers `Link: rel="related-notice"` injection on responses from that endpoint when `status: active`. - `pspace://capability/` — Capability-scoped notices. - `pspace://possibility/` — Possibility-scoped notices (public projection deferred per #2052). items: type: object required_fields: - xri optional_fields: - reason example: | applies_to: - xri: "pspace://api-endpoint/oauth-authorize" reason: "Endpoint returns 409 when no custom auth domain is configured for the requesting OIDC client" - xri: "pspace://api-endpoint/oauth-end-session" reason: "Same precondition as /oauth/authorize" visibility: type: string enum: [ public, internal ] required: true default: public description: | Per REQ-18. `public` projects this instance onto the four-surface contract (REST + llms.txt + MCP + A2A). `internal` keeps it out of public-surface projections. Possibility-scoped notices SHOULD use `internal` until per-possibility public projection ships in a future iteration. # --------------------------------------------------------------------------- # OPTIONAL FIELDS # --------------------------------------------------------------------------- remediation_url: type: string format: uri required: false description: | Optional link to a guide, runbook, or setup page partners can follow to address the situation. SHOULD point to a /docs/guides/ page; aligns with #1956 (B2) `remediation_url` for consistency. examples: - "https://possibility.space/docs/guides/custom-auth-domain" related_notices: type: array required: false description: | Optional cross-references to other notices (predecessors, successors, related events). Each entry is an object `{xri, reason}` per the standard relationship target shape. # ============================================================================= # QUALITY (P9 Quality) # ============================================================================= quality: completeness: 0.85 last_reviewed: "2026-04-26" review_status: draft reviewed_by: "phase-3-partner-unblocking" # ============================================================================= # HISTORY (P9 Temporal) # ============================================================================= _history: retention: full format: snapshot versions: - version: "0.1.1" date: "2026-04-26" author: "phase-3-partner-unblocking" summary: "PATCH — Removed top-level `conforms_to` required scalar. The relationship is captured via `relationships.conforms_to` (structured XRI), matching the established codebase convention used by registry-schema, definition-schema, and every other Layer 3 entity. Discovered while authoring B6.4 seed notice." changes: - "Removed `fields.conforms_to` (top-level required string with `const:` constraint). Added a NOTE block explaining the codebase convention." - version: "0.1.0" date: "2026-04-26" author: "phase-3-partner-unblocking" summary: "Initial notice schema (M52 Phase 3.1.6 / B6 / #2052)" changes: - "Created notice-schema.kno per Phase 2 P7 decision: one entity, scope inferred from applies_to, not three subtypes." - "Declared visibility: public on the schema (REQ-18) so platform- scoped and endpoint-scoped instances project onto REST + llms.txt surfaces in M52 (MCP/A2A deferred to M54 per Phase 2 P6 standing rule)." - "Defined fields: id, slug, type, version, conforms_to, name, summary, body (KAML), severity (info/warning/critical), status (scheduled/active/resolved), published_at, expires_at, applies_to (XRI array), visibility, remediation_url, related_notices." - "Required slug pattern YYYY-MM-DD-{kebab} so notice files sort chronologically." - "Documented bidirectional applies_to ↔ affected_by predicate pair (added to relationship-vocabulary-schema in B6.2) and the well-known pspace://platform anchor (registered in B6.3)."