diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..643b7aa8 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,85 @@ +name: Documentation + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + contract: + name: documentation contract + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + persist-credentials: false + - uses: ./.github/actions/setup-rust-cache + with: + toolchain: 1.97.1 + compiler-cache: "false" + - name: Reject a superseded source head + env: + EXPECTED_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} + run: test "$(git rev-parse HEAD)" = "$EXPECTED_HEAD" + - name: Verify source-owned documentation facts + run: | + cargo xtask docs-contract + cargo xtask public-docs + - name: Build immutable documentation bundle + run: cargo xtask docs-bundle target/docs-bundle + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: auths-docs-bundle-${{ github.event.pull_request.head.sha || github.sha }} + path: target/docs-bundle/ + if-no-files-found: error + retention-days: 7 + compression-level: 0 + + qualify: + name: documentation qualification + needs: contract + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: auths-dev/auths-docs + path: auths-docs + persist-credentials: false + - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4 + with: + name: auths-docs-bundle-${{ github.event.pull_request.head.sha || github.sha }} + path: docs-bundle + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version-file: auths-docs/.nvmrc + cache: npm + cache-dependency-path: auths-docs/package-lock.json + - name: Verify the exact product bundle + working-directory: auths-docs + run: node tools/fetch-release/verify-bundle.mjs ../docs-bundle/manifest.json + - name: Qualify the static documentation + working-directory: auths-docs + run: | + npm ci --ignore-scripts + npm run qualify + - name: Reject a superseded product head + if: github.event_name == 'pull_request' + env: + REPOSITORY: ${{ github.repository }} + EXPECTED_HEAD: ${{ github.event.pull_request.head.sha }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + current="$(curl --fail --silent --show-error --location "https://api.github.com/repos/${REPOSITORY}/pulls/${PR_NUMBER}" | jq -r .head.sha)" + test "$current" = "$EXPECTED_HEAD" diff --git a/bindings/python/python/auths/_product.py b/bindings/python/python/auths/_product.py index 7d6d856f..14355132 100644 --- a/bindings/python/python/auths/_product.py +++ b/bindings/python/python/auths/_product.py @@ -189,6 +189,13 @@ def __init__( class Auths: + """Owns one bounded actor, its authority, and effect-capable resources. + + Security: + Instances are constructed from sealed configuration and release custody and + runtime resources when closed. + """ + def __init__( self, resources: _AuthsResources, @@ -209,6 +216,17 @@ async def execute( provider: McpClosedProvider, request_id: Optional[str] = None, ) -> ExecutionResult: + """Authorize and perform exactly one action or one ordered plan. + + Returns: + A closed completed, denied, indeterminate, or recoverable outcome. + + Security: + The provider is reached only after native authorization seals the command. + + Examples: + Scenario ``auths.scenario.rest-effect/1``. + """ self._assert_active() self._assert_provider(provider) execution = McpExecutionResources( @@ -236,6 +254,14 @@ async def resume( reference: ExecutionReference, provider: McpClosedProvider, ) -> ExecutionResult: + """Continue a recoverable execution from its opaque reference. + + Returns: + A closed execution outcome. Unknown provider state never becomes success. + + Security: + Only an SDK-minted reference bound to this runtime is accepted. + """ self._assert_active() self._assert_provider(provider) if type(reference) is not ExecutionReference: @@ -261,6 +287,14 @@ async def recover( provider: McpClosedProvider, request_id: Optional[str] = None, ) -> ExecutionResult: + """Recover a prior request without authorizing a different action. + + Returns: + A closed execution or recovery outcome for the exact request. + + Security: + Recovery preserves replay and provider-unknown state. + """ self._assert_active() self._assert_provider(provider) result = await recover_mcp_closed( @@ -285,6 +319,17 @@ async def delegate( name: str = "delegated-agent", expires_in_seconds: int = 300, ) -> Auths: + """Create a child session whose authority is no broader than this session. + + Returns: + A separately disposable child Auths session. + + Security: + Service changes, expiry violations, and authority widening are rejected. + + Examples: + Scenario ``auths.scenario.delegation/1``. + """ self._assert_active() profile, permissions, _, audiences = resources_for_mcp_authority(authority) parent_profile, _, _, _ = resources_for_mcp_authority(self.authority) diff --git a/bindings/python/tools/check_public_docs.py b/bindings/python/tools/check_public_docs.py new file mode 100644 index 00000000..13a7ad68 --- /dev/null +++ b/bindings/python/tools/check_public_docs.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import ast +import json +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +PRODUCT = ROOT / "python" / "auths" / "_product.py" +REQUIRED = {"Auths": {"execute", "resume", "recover", "delegate"}} + + +def main() -> None: + module = ast.parse(PRODUCT.read_text(encoding="utf-8")) + missing: list[str] = [] + for node in module.body: + if isinstance(node, ast.ClassDef) and node.name in REQUIRED: + if not ast.get_docstring(node): + missing.append(node.name) + methods = { + child.name: child + for child in node.body + if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef)) + } + for name in REQUIRED[node.name]: + method = methods.get(name) + if method is None or not ast.get_docstring(method): + missing.append(f"{node.name}.{name}") + if missing: + raise SystemExit(f"Python P0 documentation missing: {', '.join(missing)}") + print(json.dumps({"schema": "auths.public-docs.python/1", "p0": 5, "missing": []})) + + +if __name__ == "__main__": + main() diff --git a/bindings/python/tools/docs_surface.py b/bindings/python/tools/docs_surface.py new file mode 100644 index 00000000..2706e254 --- /dev/null +++ b/bindings/python/tools/docs_surface.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import json +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +def main() -> None: + module: str | None = None + symbols: list[dict[str, str]] = [] + for line in (ROOT / "api" / "public-api.txt").read_text(encoding="utf-8").splitlines(): + if line.startswith("[") and line.endswith("]"): + module = line[1:-1] + elif line: + if module is None: + raise SystemExit("public API symbol has no module") + symbols.append({"module": module, "name": line}) + symbols.sort(key=lambda symbol: (symbol["module"], symbol["name"])) + print(json.dumps({"schema": "auths.docs.python-surface/1", "package": "auths", "symbols": symbols}, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/bindings/typescript/api/tsdoc.json b/bindings/typescript/api/tsdoc.json new file mode 100644 index 00000000..63ce51d3 --- /dev/null +++ b/bindings/typescript/api/tsdoc.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "tagDefinitions": [ + { "tagName": "@security", "syntaxKind": "block" }, + { "tagName": "@scenario", "syntaxKind": "block" } + ], + "supportForTags": { + "@security": true, + "@scenario": true + } +} diff --git a/bindings/typescript/src/product.ts b/bindings/typescript/src/product.ts index 6748d5a7..906b7ee6 100644 --- a/bindings/typescript/src/product.ts +++ b/bindings/typescript/src/product.ts @@ -129,6 +129,13 @@ export interface Auths { readonly actor: Actor; readonly authority: Authority; readonly diagnostics: readonly string[]; + /** + * Authorizes and performs exactly one action or one ordered plan. + * + * @returns A closed completed, denied, indeterminate, or recoverable outcome. + * @security The provider is reached only after native authorization seals the command. + * @scenario auths.scenario.rest-effect/1 + */ execute(input: Readonly<{ action: McpAction; provider: McpClosedProvider; @@ -139,6 +146,12 @@ export interface Auths { provider: McpClosedProvider; requestId?: string; }>): Promise; + /** + * Continues a recoverable execution from its opaque reference. + * + * @returns A closed execution outcome; an unknown provider result never becomes success. + * @security References are SDK-minted and bound to the original execution state. + */ resume(input: Readonly<{ reference: ExecutionReference; provider: McpClosedProvider; @@ -148,6 +161,13 @@ export interface Auths { provider: McpClosedProvider; requestId?: string; }>): Promise; + /** + * Creates a child SDK session with authority no broader than this session. + * + * @returns A separately disposable child session. + * @security Delegation rejects service changes, expiry violations, and authority widening. + * @scenario auths.scenario.delegation/1 + */ delegate(input: Readonly<{ authority: McpToolAuthority; name?: string; @@ -345,6 +365,13 @@ export function createAuthsConfiguration( return configuration; } +/** + * Opens the five-verb Auths product surface from a parsed configuration. + * + * @returns An SDK session whose authority and resources are owned until disposal. + * @security Configuration selects an explicit development or production trust boundary. + * @scenario auths.scenario.rest-effect/1 + */ export async function createAuths(configuration: AuthsConfiguration): Promise { const resources = configurationResources.get(configuration); if (resources === undefined) throw new TypeError("Auths configuration was not created by an integration"); diff --git a/bindings/typescript/tools/docs-surface.mjs b/bindings/typescript/tools/docs-surface.mjs new file mode 100644 index 00000000..0c9391ab --- /dev/null +++ b/bindings/typescript/tools/docs-surface.mjs @@ -0,0 +1,17 @@ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const snapshot = fs.readFileSync(path.join(root, "api/public-api.txt"), "utf8"); +const symbols = snapshot + .split("\n") + .filter((line) => line && !line.startsWith("#")) + .map((line) => { + const [entrypoint, name, kind] = line.split("\t"); + if (!entrypoint || !name || !kind) throw new TypeError(`invalid public API line: ${line}`); + return { entrypoint, name, kind }; + }) + .sort((left, right) => `${left.entrypoint}\0${left.name}`.localeCompare(`${right.entrypoint}\0${right.name}`)); + +process.stdout.write(`${JSON.stringify({ schema: "auths.docs.typescript-surface/1", package: "@auths-dev/sdk", symbols }, null, 2)}\n`); diff --git a/bindings/typescript/tools/public-docs.mjs b/bindings/typescript/tools/public-docs.mjs new file mode 100644 index 00000000..82e75a03 --- /dev/null +++ b/bindings/typescript/tools/public-docs.mjs @@ -0,0 +1,19 @@ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const product = fs.readFileSync(path.join(root, "src/product.ts"), "utf8"); +const required = [ + ["create", /\/\*\*[\s\S]*?@scenario auths\.scenario\.rest-effect\/1[\s\S]*?\*\/\s*export async function createAuths/], + ["delegate", /\/\*\*[\s\S]*?@scenario auths\.scenario\.delegation\/1[\s\S]*?\*\/\s*delegate\(/], + ["execute", /\/\*\*[\s\S]*?@scenario auths\.scenario\.rest-effect\/1[\s\S]*?\*\/\s*execute\(/], + ["resume", /\/\*\*[\s\S]*?@security[\s\S]*?\*\/\s*resume\(/], +]; + +const missing = required.filter(([, pattern]) => !pattern.test(product)).map(([name]) => name); +if (missing.length > 0) { + throw new Error(`TypeScript P0 documentation missing: ${missing.join(", ")}`); +} + +process.stdout.write(JSON.stringify({ schema: "auths.public-docs.typescript/1", p0: required.length, missing: [] })); diff --git a/docs/public-api-documentation-policy.toml b/docs/public-api-documentation-policy.toml new file mode 100644 index 00000000..f8a33c3a --- /dev/null +++ b/docs/public-api-documentation-policy.toml @@ -0,0 +1,29 @@ +schema = "auths.public-docs-policy/1" +maintained_languages = ["rust", "typescript", "python"] + +[[tier]] +name = "P0" +operations = ["auths.operation.create/1", "auths.operation.delegate/1", "auths.operation.execute/1", "auths.operation.resume/1", "auths.operation.verify/1"] +required_sections = ["summary", "outcomes", "security", "scenario"] + +[[tier]] +name = "P1" +surface = "maintained-public-topology" +required_sections = ["summary"] + +[[tier]] +name = "P2" +surface = "extension-ports" +required_sections = ["summary", "invariants"] + +[[owner]] +surface = "rust" +path = "core,exchange,product" + +[[owner]] +surface = "typescript" +path = "bindings/typescript" + +[[owner]] +surface = "python" +path = "bindings/python" diff --git a/docs/specs/0040-stripe-quality-documentation-platform.md b/docs/specs/0040-stripe-quality-documentation-platform.md new file mode 100644 index 00000000..d3adc99d --- /dev/null +++ b/docs/specs/0040-stripe-quality-documentation-platform.md @@ -0,0 +1,1326 @@ +# AP-SPEC-040: Stripe-Quality Documentation and Developer Portal + +**Status:** Specified across `auths-proof` and the separate `auths-proof-docs` +repository. This repository owns source documentation, product facts, semantic +mapping, and immutable release metadata. `auths-proof-docs` owns authored public +content, rendering, reference generation, qualification, and deployment. +Neither repository acquires a mutable sibling dependency. + +**Depends on:** [AP-SPEC-034 public naming +consolidation](0034-auths-public-naming-consolidation.md), [AP-SPEC-038 open +production substrate](0038-production-runtime-custody-observability-and-assurance.md), +the published Rust, TypeScript, and Python package contracts, and the canonical +release and semantic identities + +**Related:** [AP-SPEC-039 enterprise coordination and +operations](0039-enterprise-coordination-and-operations-plane.md). Enterprise +documentation may be added later, but it must not obscure or gate the complete +open, self-hosted path. + +**Execution map:** [Platform and content epic coordination](0040/README.md), +including the binding [platform/editorial ownership +contract](0040/content/epic_0.md). + +## 1. Product decision + +Auths will have one beautiful, fast, public documentation experience that +makes exact authority feel simple before revealing its depth. A new developer +must be able to protect one REST effect in fifteen minutes using five verbs: +`create`, `delegate`, `execute`, `resume`, and `verify`. The same site must let +an experienced security or infrastructure engineer descend into lifecycle +state, custody, profiles, wire formats, threat boundaries, differential +evidence, and formal assurance without encountering a second vocabulary. + +The documentation is a product surface, not a generated appendix. It has four +equal responsibilities: + +1. explain why Auths exists in ordinary language; +2. produce a safe first success quickly; +3. provide exact, tested reference material for every supported public + surface; and +4. remain directly usable by humans, terminals, coding agents, and other + machines. + +The north star is Stripe-quality comprehension, not a visual clone of Stripe. +Auths should adopt the structural lessons that make Stripe's documentation +effective while developing its own authority-specific visual and conceptual +grammar. + +### 1.1 Two-lane ownership + +AP-SPEC-040 has a platform lane and an editorial lane. They meet only through +typed inputs to one verified page graph: + +- the platform lane owns generated product facts, qualified scenarios, + composition models, rendering, and release machinery; +- the editorial lane owns reader journeys, recommendations, explanations, and + conceptual diagrams; and +- no public block may have more than one provenance owner. + +If a software change could make a statement false, the value is supplied by an +immutable product fact or tested scenario rather than copied into MDX. HTML, +Markdown, navigation, search, and agent-readable output are projections of the +same verified page graph, never independently authored corpora. + +## 2. Evidence from Stripe's documentation + +This specification is informed by the following current, public Stripe +patterns: + +- Stripe's [documentation landing page](https://docs.stripe.com/) starts from + outcomes and products instead of presenting the API reference as the whole + product. +- Its [developer resources](https://docs.stripe.com/development) group CLI, + SDKs, APIs, agents, MCP, testing, versioning, security, and extension tools + into a coherent developer platform. +- Its [SDK landing page](https://docs.stripe.com/sdks) makes official language + libraries, versioning, support policy, OpenAPI, and adjacent tools easy to + discover. +- Its [API overview](https://docs.stripe.com/apis) teaches authentication, + request behavior, testing, limits, and errors before sending readers into + individual operations. +- Its [API reference](https://docs.stripe.com/api) and individual operation + pages, such as [Create a + customer](https://docs.stripe.com/api/customers/create), keep request, + response, return behavior, and parameter details together. +- Stripe's [quickstart catalog](https://docs.stripe.com/quickstarts) describes + end-to-end examples with multiple languages and frameworks, scroll-linked + implementation steps, and downloadable or agent-assisted starting points. +- Stripe explicitly publishes [machine-readable documentation + surfaces](https://docs.stripe.com/agents): appending `.md` to a documentation + URL returns Markdown, and the same developer area points agents toward + indexed skills and tools. +- Its [MCP documentation](https://docs.stripe.com/mcp) separates documentation + search and API-detail tools from broad write tools, allowing a client to + retrieve only the context it needs. + +Auths will adopt the outcome-first hierarchy, deep reference, tested +multi-language examples, and machine-readable delivery. It will improve on the +pattern for Auths' domain by making trust boundaries, authorization versus +execution, and denial versus indeterminate versus provider-unknown outcomes +visible throughout the site. + +## 3. Success criteria + +The initial public release is complete only when all of the following are true: + +- An unfamiliar developer can install one maintained SDK, run the local + reference path, and authorize one exact REST effect in under fifteen minutes. +- A reader can answer “what is Auths?”, “why is this not OAuth?”, and “what is + the smallest thing I can build?” from the home page without protocol terms. +- Every maintained Rust, TypeScript, and Python public operation has an exact + reference page or an explicit, machine-checked `not supported` state. +- Language selection is consistent across a page and persists while navigating. +- Every displayed code sample comes from a file that CI compiles or executes + against published artifacts. +- Equivalent Rust, TypeScript, and Python examples produce the same normalized + outcomes against the same fixtures and reference runtime. +- Every public HTML content page has a canonical Markdown representation. +- Search can resolve product vocabulary, SDK symbols, stable error codes, + profiles, concepts, and common synonyms. +- The site remains useful without client-side JavaScript; JavaScript enhances + tabs, search, and diagrams but does not contain the documentation. +- The public site meets WCAG 2.2 AA, scores at least 95 for accessibility and + 90 for performance in the maintained Lighthouse profile, and has no serious + automated accessibility violation. +- No draft plan, scratch document, secret, internal release note, or + unsupported claim is published accidentally. + +Usability qualification must include at least five developers who have never +worked in this repository. At least four must complete the REST quickstart +without verbal help. Every hesitation longer than two minutes becomes a docs +issue even if the user eventually succeeds. + +## 4. Audience and primary jobs + +The site serves six audiences through one information architecture: + +| Audience | First question | Primary destination | +| --- | --- | --- | +| Application developer | How do I protect one endpoint? | REST quickstart | +| Agent developer | How do I give an agent narrow authority? | Agent authority guide | +| SDK consumer | What does this function accept and return? | Language-aware SDK reference | +| Security architect | What is trusted, signed, stateful, and fail-closed? | Architecture and threat boundaries | +| Platform operator | How do I deploy, observe, recover, and rotate custody? | Operations guides | +| Auditor or implementer | What are the exact semantics and evidence? | Protocol and assurance reference | + +The home page must not force these users through the same depth. It offers a +single recommended start and then clear routes by job. + +## 5. Progressive-disclosure contract + +Progressive disclosure is structural, not merely a collection of collapsed +sections. Every concept has one name and appears at increasing levels of depth: + +| Level | Reader intent | Content | +| --- | --- | --- | +| 0 — Understand | “Why should I care?” | One concrete story, outcomes, five nouns and five verbs | +| 1 — Start | “Show me the safe path.” | Install, local sandbox, one complete effect, one receipt | +| 2 — Build | “Adapt this to my application.” | Guides, profiles, approvals, recovery, framework recipes | +| 3 — Operate | “Run this reliably.” | Deployment, custody, stores, observability, backup, reconciliation | +| 4 — Inspect | “Explain exactly what happened.” | Outcomes, receipts, disclosure, error codes, state transitions | +| 5 — Verify | “Show me the contract and evidence.” | Protocol, wire formats, fixtures, formal and differential assurance | + +A page may link downward but must not duplicate the deeper explanation. The +simple path uses concrete defaults and names the next decision only when the +reader reaches it. + +Security-critical facts are exempt from concealment. A warning that changes +whether an effect is safe, repeatable, private, or authorized must appear at +the point of action; it cannot exist only in an “advanced” accordion. + +Every guide follows this order: + +1. **Outcome:** what the reader will have working. +2. **Before you begin:** the smallest real prerequisite set. +3. **Build:** executable steps with a visible progress rail. +4. **What Auths proved:** a plain-language explanation of the resulting + authority and receipt. +5. **Failure paths:** denial, indeterminate, replay, expiry, mutation, and + unknown provider outcome where relevant. +6. **Take it further:** links to operations, architecture, and exact reference. + +## 6. Information architecture + +The public navigation is organized around user intent rather than repository +layers or crate names. Content Epic 1 owns the final route selection, labels, +card ordering, and contextual trees. Platform Epic 6 supplies the typed models +and validation but does not hard-code this taxonomy. + +```text +Primary topics Utility destinations +├── Get started ├── APIs & SDKs +├── Identity & trust ├── Search +├── Authority └── GitHub +├── Agents +├── Operations Cross-linked domain +└── Developers └── Assurance +``` + +Crate and package names remain searchable and appear on reference pages, but +they do not determine the top-level navigation. Each primary topic opens a +curated landing page before its exhaustive contextual tree. Landing pages +recommend; contextual navigation enumerates. + +The default home-page journey is: + +```text +"I need to authorize one effect" + | + v + REST API quickstart + | + v + create -> delegate -> execute -> verify + | + v + human-readable receipt + | + +------+-------+ + | | + v v + adapt a profile understand architecture +``` + +## 7. UX + +### 7.1 Visual character + +The visual system should feel calm, exact, and capable. It must avoid the +“cybersecurity dashboard” cliché of neon colors, constant warning states, and +decorative network graphics. Authority and lifecycle state should be legible +through typography, spacing, restrained color, and consistent diagrams. + +The design system provides semantic colors for: + +- verified or completed; +- denied or rejected; +- indeterminate or unavailable; +- recoverable or outcome unknown; and +- explanatory, non-status information. + +Color is never the only carrier of meaning. Outcome components always include +an icon, label, and short text. + +The checked Auths SVG is the canonical brand mark for the header, footer, +metadata, and generated social assets. Do not recreate it with CSS geometry, +text glyphs, or an approximate icon. The site uses one restrained, open icon +family for navigation and actions. GitHub, search, clipboard, Markdown, and +external-link actions use real icons from that family, with accessible labels; +production imports must be per icon or equivalently tree-shaken. + +### 7.2 Global shell and home page + +The desktop header has two deliberate rows: the official Auths mark and +“Auths Docs” at the upper left, search centered independently, and the GitHub +icon plus external-link indicator at the upper right. `Start`, `SDKs`, +`Runtime API`, `Concepts`, `Architecture`, and `Operations` occupy the +lower-left row. A bounded `More` menu contains `Integrations` and `Assurance`; +it must not become a second, unstructured navigation tree. + +Contextual documentation or reference navigation begins at the left viewport +edge below the header. It is collapsible on desktop and becomes a drawer on +narrow screens; collapsing it widens the reading surface rather than leaving +an empty centered gutter. + +One design token owns the full header height. Sticky contextual navigation, +page outlines, reference code rails, restored-navigation controls, anchor +scroll margins, and viewport-height calculations consume that token. No +component may copy a numeric header offset. + +The centered search control opens real local search with `Command + K` and +`Control + K`, keyboard focus management, and an accessible dialog. It must +not be decorative or resize the header when open. On narrow screens the brand +and GitHub icon remain in the first row, search occupies its own row, and the +global links remain horizontally scrollable or enter one accessible menu +without changing their information hierarchy. + +```text ++--------------------------------------------------------------------------------+ +| [Auths logo] Auths Docs Search docs, symbols, errors... GitHub [↗] | +| Start SDK Concepts Architecture | ++--------------------------------------------------------------------------------+ +| Give people and agents exact authority—without giving away the account. | +| | +| [Protect a REST effect in 15 minutes] [Understand Auths] | +| | +| create -> delegate -> execute -> resume -> verify | ++--------------------------------------------------------------------------------+ +| Start with an outcome | +| [REST API] [Agent delegation] [Cross-company] [Infrastructure] [Approvals] | ++--------------------------------------------------------------------------------+ +| Build with Auths | +| [Rust] [TypeScript] [Python] [Runtime API] [CLI] [MCP] | ++--------------------------------------------------------------------------------+ +| Why Auths | +| Identity says who. Auths proves the exact action they may perform. | +| [See the architecture] [Compare alternatives] | ++--------------------------------------------------------------------------------+ +``` + +The hero must not lead with “capabilities,” “CBOR,” “attenuation algebra,” or +crate names. The first screen contains one promise, one primary quickstart, +the five verbs, search, and language access. + +### 7.3 Guide page + +```text ++----------------------+--------------------------------------+------------------+ +| Guide navigation | Protect a REST effect | On this page | +| | | | +| 1 Install ✓ | [Rust] [TypeScript] [Python] | Outcome | +| 2 Define action ✓ | +----------------------------------+ | Build | +| 3 Create ● | | exact runnable code | | What was proved | +| 4 Execute | +----------------------------------+ | Failure paths | +| 5 Verify | | Next steps | +| | The authority permits only... | | ++----------------------+--------------------------------------+------------------+ +| Copy for LLM · View Markdown · Edit · Report an issue | ++--------------------------------------------------------------------------------+ +``` + +On narrow screens, the left navigation becomes a drawer, the progress rail +becomes a compact header, and the table of contents becomes an inline outline. +Code never requires horizontal page scrolling beyond its own container. +The guide navigation is flush with the left viewport edge rather than placed +inside the centered prose shell. A desktop collapse control remains available, +and restoring navigation does not change the reader's semantic scroll position. + +### 7.4 Reference page + +```text ++----------------------+--------------------------------------+------------------+ +| Reference | create | Rust TS Python | +| Search symbols | Create bounded root authority | | +| | | Install | +| Authority | Signature | Request | +| create | create(request) -> AuthorityResult | Response | +| delegate | | Errors | +| Execution | Parameters | Related guides | +| execute | Returns | | +| resume | Outcomes | | ++----------------------+--------------------------------------+------------------+ +``` + +Reference pages remain concept-first. A Rust trait name, TypeScript interface, +and Python class can be different projections of the same semantic operation; +the page begins with the shared meaning and then shows language-specific names, +types, and examples. + +The reference shell has three distinct responsibilities: left contextual +navigation, middle meaning/reference content, and a right language-aware code +rail that may remain sticky within the current section. The middle and right +columns share one visual plane and are not separated by a heavy vertical rule; +the dark bounded code component supplies its own edge. The code rail may pair +tested source with a typed normalized-result block. Selecting a language in the +rail updates every applicable source and symbol panel on the page. + +An **SDK reference** documents installed Rust, TypeScript, and Python +operations and types. A **runtime API reference** documents HTTP methods, +paths, carriers, trust context, outcomes, and retry behavior. Titles, +navigation, installation text, URLs, and search records use those exact +surface names and never label an SDK page merely “API reference.” + +### 7.5 Page tools + +Every content page exposes the following actions in a consistent location: + +- **Copy for LLM**, which copies the canonical page Markdown; +- view the canonical `.md` URL; +- copy the current section link; +- copy the smallest relevant code example; +- copy a bounded “implement this with Auths” prompt containing the page URL, + selected language, package version, and explicit task—but no secrets or page + analytics; +- edit the human-authored source on GitHub where permitted; +- report an issue with page identity and release version prefilled; and +- switch the documentation version. + +Page-level Copy/View Markdown actions appear directly beneath the page title +and description. Long reference pages additionally expose section-level +**Copy for LLM** and **View as Markdown** actions beside the section heading. +The section projection contains that heading, its relevant prose, all declared +language examples, generated facts, warnings, semantic identity, and release +identity. It excludes neighboring sections, code from another semantic step, +and navigation chrome. + +The copy-as-Markdown result must be useful independently. It includes title, +summary, prerequisites, all language examples under explicit headings, +security callouts, reference links, page identity, and release identity. It +excludes navigation chrome, cookie text, hidden UI labels, and analytics. + +## 8. Multi-language SDK experience + +Rust, TypeScript, and Python are equal maintained SDKs. The site must never +describe one as canonical implementation documentation and the others as +secondary wrappers, even though Rust owns protocol semantics internally. + +### 8.1 Language state + +- The selector offers `Rust`, `TypeScript`, and `Python` in that order only + when all are relevant. A page may offer a documented subset. +- Selection applies to all code groups and symbol panels on the page. +- Selection persists across navigation in local storage and is represented in + `?lang=rust|typescript|python` so a link is shareable. +- The query value is parsed into a closed language type. Unknown values are + ignored rather than reflected into the page. +- Server-rendered HTML contains every language example. CSS and minimal + JavaScript select the visible panel; content does not arrive through a later + API request. +- Keyboard users can move between tabs with standard tab-list behavior, and + screen readers receive the language and panel relationship. +- A desktop-only “Compare languages” action may show two implementations side + by side. It is an enhancement, not a separate content source. + +### 8.2 Code and result rendering + +All source presentation composes two closed components: + +```ts +interface CodeBlockProps { + language: "rust" | "typescript" | "python"; + code: string; + isBash?: boolean; + label?: string; +} + +interface CodeBlockWithResultProps extends CodeBlockProps { + result: string; + resultLanguage?: "json" | "text" | "bash" | "rust" | "typescript" | "python"; + resultLabel?: string; +} +``` + +`isBash` means the source is a shell command associated with the selected SDK, +so Bash grammar overrides the SDK language grammar without changing global +language state. Result grammar defaults to JSON and must be declared when the +normalized result is text, Bash, or another maintained language. Both +components share one theme, toolbar, copy behavior, spacing system, overflow +policy, accessibility contract, and syntax renderer. A result is visually +distinct inside the same bounded block rather than an unrelated second card. + +The component receives verified source and result text from scenario or +reference page models. MDX cannot use it to smuggle a second untested +executable example. Canonical Markdown emits explicit language-labelled fences +for source and result. + +### 8.3 One scenario, three idiomatic implementations + +Examples are not generated by transliterating Rust. Each language remains +idiomatic, while a shared scenario manifest owns: + +- the purpose and profile; +- fixture identities; +- exact application bytes; +- clock and lifecycle inputs; +- expected normalized outcomes; +- stable error codes; +- receipt commitments; and +- security assertions. + +The three source files execute against the same immutable reference release. +CI captures their normalized results and compares them with the Rust-owned +fixture. The documentation build reads the exact tested source files. It must +never copy code from prose or maintain a second hidden snippet. + +If an SDK does not support a capability, the capability registry renders a +clear unavailable state and links to the owning issue. Documentation must not +simulate parity with language-local helper code that changes Auths meaning. + +### 8.4 Reference generation + +The SDK reference combines generated facts with human explanation: + +- Rust public items and signatures come from release-scoped Rustdoc JSON or a + purpose-built bounded export. +- TypeScript exports and declarations come from the installed package's + frozen public API snapshot. +- Python symbols, signatures, typing, and doc summaries come from the installed + wheel's public API contract. +- Cross-language semantic operation identities come from one release manifest. +- Human-authored introductions, examples, guidance, and security notes are + joined by stable operation identity, never by display name matching. + +A missing join, duplicate identity, undocumented public symbol, or stale +symbol reference fails the build. + +## 9. Architecture and conceptual documentation + +Architecture pages must explain relationships visually and then provide an +equivalent text description. The default system map is horizontal and compact: + +```text +identity evidence exact authority sealed command receipt + | | | | + v v v v ++-----------+ +-------------+ +--------------+ +-----------+ +| identity | ------> | Auths verify| ----> | closed | -> | durable | +| provider | context | + lifecycle | claim | gateway | | evidence | ++-----------+ +------+------+ +--------------+ +-----------+ + | + v + replay / budget / + recovery state + +Transport carries bytes. Custody signs commitments. Neither grants authority. +``` + +The architecture section must cover: + +- identity versus authority; +- the five nouns and five verbs; +- exact application-byte commitment; +- delegation and attenuation; +- approvals bound to exact transactions; +- offline verification versus stateful enforcement; +- replay, budget, expiry, revocation, and recovery state; +- authorization, provider delivery, observed effect, and receipts as distinct + facts; +- sealed commands and closed gateways; +- cryptographic, identity, custody, transport, store, and provider agility; +- Rust ownership of semantics and thin language projections; +- open-core versus optional enterprise boundaries; and +- the scope and limits of formal, differential, and operational evidence. + +Mermaid diagrams are allowed as authored source, but the build must render +them deterministically to accessible SVG with pinned tooling. Each diagram has +a text alternative and remains understandable in Markdown-only output. Motion +is optional and disabled under reduced-motion preferences. + +## 10. API and reference surfaces + +“API reference” is divided into explicit surfaces so readers do not confuse a +language method, runtime route, profile, and wire object. + +### 10.1 SDK reference + +Organized by semantic operation, with language-specific symbols, types, +examples, errors, limits, and availability. It includes the simple five-verb +surface first, followed by deliberate deeper groups for identity, trust, +approvals, custody, runtime, inspection, diagnostics, profiles, and testkit. +Installation panels use the SDK package coordinates and Bash-highlighted +commands while the operation examples remain highlighted as the selected SDK +language. The page title, navigation, search kind, and canonical URL identify +this surface as an SDK reference, never a generic API reference. + +### 10.2 Runtime API reference + +Documents the HTTPS production boundary, content types, limits, authentication +context, exact routes, status handling, and binary request and response +contract. Every operation page contains: + +- purpose and trust boundary; +- method and path; +- required profile; +- request carrier and byte limit; +- successful and non-success outcome families; +- retry meaning; +- stable codes; +- executable curl or SDK examples where safe; and +- related lifecycle and security guidance. + +The reference must not imply that a successful HTTP response alone means an +effect was authorized or completed. +Its code rail may expose safe `curl` or SDK alternatives, but the middle +contract remains method/path and wire behavior rather than an SDK function +signature. + +### 10.3 Profile reference + +Every maintained profile page owns its exact action, policy inputs, trusted +evidence, required and executed configuration, denial and indeterminate +outcomes, provider boundary, credential timing, recovery behavior, receipt +claims, hard limits, and qualification evidence. Profile pages link to their +domain guide and runnable example. + +### 10.4 Protocol and assurance reference + +Documents canonical objects, version identities, algorithms, limits, stable +result codes, fixture manifests, and assurance claims. Raw byte layouts belong +here, not in the quickstart. Every claim links to the exact release evidence +that supports it and names what the evidence does not prove. + +## 11. Search, discovery, and glossary + +The first release uses a static, build-scoped search index so documentation +remains self-hostable and does not leak queries to a third party. Search ranks: + +1. exact SDK symbols, route names, profile identities, and stable error codes; +2. page titles and aliases; +3. headings; +4. summaries and body text; and +5. historical names only when an explicit synonym exists. + +The index stores document version, language applicability, audience, content +kind, support status, and release identity. Search results display these facts +and never mix `next` documentation into a stable-release result without a +visible label. + +A checked glossary owns preferred terms and synonyms. For example, searches +for “permission,” “scope,” “role,” or “token” may lead to authority pages while +preserving the distinction between those concepts. Unknown synonyms are not +silently inferred during the build. + +## 12. Machine-readable and agent-first delivery + +Every canonical HTML route has a Markdown twin: + +```text +GET /architecture/trust-boundaries +GET /architecture/trust-boundaries.md +GET /architecture/trust-boundaries/sections/evidence.md +``` + +The Markdown response has content type `text/markdown; charset=utf-8`, a +canonical link header, release identity, and cache validators. A missing `.md` +route for a public content page fails deployment qualification. + +Templates may also publish bounded section Markdown at +`//sections/.md`. Section routes are generated from +closed page-model identities, not mutable heading text, and include their +parent canonical URL and release identity. + +The site also publishes: + +- `/llms.txt`: a concise index of the product model and important page URLs; +- `/llms-full.txt`: a bounded, release-scoped compilation of the essential + public documentation, excluding generated exhaustive symbol reference; +- `/.well-known/auths-docs.json`: documentation version, release identity, + languages, package versions, sitemap, search index, Markdown convention, and + integrity metadata; +- `/sitemap.xml`: canonical human routes; +- `/search-index.json`: a bounded public search catalog without analytics; and +- `/reference/manifest.json`: operation, SDK symbol, profile, error, and + evidence identities for the selected release. + +Phase two may add a read-only documentation MCP server with only: + +```text +search_auths_docs(query, version?, language?) +read_auths_doc(page_id, version?, section?) +resolve_auths_symbol(symbol, language, version?) +explain_auths_error(code, version?) +``` + +These tools return bounded excerpts plus canonical URLs. They never execute an +Auths operation, accept credentials, mutate a resource, or blur documentation +access with the product's authority MCP surfaces. + +## 13. Architecture + +The documentation implementation remains in the separate `auths-proof-docs` +repository, as required by the monorepo contract. It consumes published, +immutable artifacts from `auths-proof`; it never imports this checkout through +a sibling path. + +```text +auths-proof release + packages + docs contract + fixtures + evidence + | + v + immutable artifact fetch + | + v ++---------------- auths-proof-docs ----------------+ +| authored MD/MDX | +| generated reference join | +| tested example sources | +| Vinext build + custom Auths design system | +| static search + Markdown renderer | ++-------------------------+-------------------------+ + | + v + immutable static output + | + +------------+-------------+ + | | + v v + CDN / docs.auths.dev release artifact archive +``` + +### 13.1 Tooling decisions + +Use the following concrete stack. These choices are part of the specification, +not suggestions to revisit during implementation: + +- **Runtime and package manager:** Node 22 and npm with a committed lockfile. + CI uses deterministic installs and rejects lockfile drift. +- **Site generator:** Vinext on Vite with React server components and + `@mdx-js/rollup`. A custom Auths shell owns navigation, reference layouts, + language state, and visual identity. +- **Authoring:** `.mdx` for every human-authored public page. Plain Markdown is + valid MDX, so prose stays simple while typed components remain available. +- **Types and parsing:** strict TypeScript and closed page-model parsers that + convert untrusted files and release artifacts into typed values. +- **Client behavior:** server-rendered documentation with small React client + components for language state, search, navigation, and copy actions. +- **Code rendering:** Shiki with pinned grammars and themes. +- **Icons and brand assets:** the checked official Auths SVG plus one pinned, + open icon family. Load icons individually or through a build-proven + tree-shakable path; root imports that pull an entire icon catalog fail the + client bundle budget. Text glyphs do not substitute for product-action icons. +- **Search:** Pagefind, built from the final static output and served without a + hosted search dependency. +- **Diagrams:** pinned Mermaid tooling rendered to accessible SVG during the + build. Production pages do not execute Mermaid in the browser. +- **Content transforms:** pinned `remark` and `rehype` plugins, including an + Auths-owned MDX policy plugin. +- **Browser and accessibility tests:** Playwright and `axe-core`. +- **Performance and visual tests:** Lighthouse CI and Playwright screenshot + comparisons on a bounded set of stable page templates. +- **Links:** a pinned, cross-platform link checker that validates HTML, + Markdown twins, anchors, and release-pinned source links. +- **Deployment:** immutable static output compatible with Vercel, Cloudflare + Pages, or ordinary object storage plus CDN. + +Exact patch versions are locked in the docs repository. Major upgrades are +ordinary reviewed changes with a rendered preview and complete qualification; +no build dependency floats in CI. + +Do not introduce a database, runtime CMS, account system, server-rendered +dependency, or production-time dependency on GitHub for the first release. + +UX prototypes may use a different local framework to settle interaction and +visual contracts. They are evidence for component behavior, not permission to +replace this production stack, copy framework-specific runtime code, or add a +mutable dependency on the prototype repository. Promote the proven contracts +through the typed documentation components described here. + +### 13.2 Authoring format and MDX policy + +There are three deliberately different representations: + +1. **Human-authored `.mdx`:** concepts, quickstarts, architecture, integration, + security, and operations guidance. +2. **Generated page models:** signatures, parameters, returns, routes, errors, + profiles, limits, versions, and evidence. These are typed data rendered by + shared route templates; they are not generated or hand-edited MDX files. +3. **Executable example files:** real `.rs`, `.ts`, and `.py` sources compiled + or run in clean consumers. MDX embeds them by scenario identity rather than + duplicating them in fenced code blocks. + +MDX is constrained so documentation remains content rather than an unbounded +application framework: + +- pages may use only globally registered, allowlisted documentation + components; +- arbitrary component imports, inline scripts, network access, and build-time + side effects in MDX are rejected; +- authored pages never contain hand-written parameter tables, endpoint lists, + support matrices, package versions, or copied executable examples; +- raw HTML is rejected except for an explicitly audited allowlist; +- each component receives schema-parsed props and renders in both HTML and + canonical Markdown; and +- plans, research, private notes, and repository READMEs may remain `.md` + because they are outside the public content collection. + +The deployed `/.md` representation is generated from the same parsed +page model as HTML. It is an output, never a second authored source. + +### 13.3 Repository layout + +```text +auths-proof-docs/ +├── README.md +├── package.json +├── package-lock.json +├── astro.config.ts +├── tsconfig.json +├── docs/ +│ ├── plans/ +│ ├── content-contract.md +│ └── authoring.md +├── site/ +│ ├── src/content/docs/ # human-authored public .mdx +│ ├── src/components/ # allowlisted documentation components +│ ├── src/layouts/ +│ ├── src/pages/reference/ # templates over typed page models +│ ├── src/generated/ # ignored build output; never committed +│ ├── src/styles/ +│ ├── public/ +│ └── tests/ +├── examples/ +│ ├── scenarios/ # typed expected-outcome manifests +│ ├── rust/ +│ ├── typescript/ +│ └── python/ +├── schemas/ +│ ├── docs-contract/ +│ ├── page-model/ +│ └── scenario/ +├── tools/ +│ ├── fetch-release/ +│ ├── extract-rust/ +│ ├── extract-typescript/ +│ ├── extract-python/ +│ ├── build-page-model/ +│ ├── render-markdown/ +│ └── check-links/ +└── tests/ + ├── contract/ + ├── browser/ + └── visual/ +``` + +Plans and internal research are never placed inside the public content +collection. Generated reference pages are materialized only in a temporary +build directory. The repository commits schemas, templates, mapping manifests, +authored MDX, and executable examples—not thousands of generated pages. + +### 13.4 Release documentation contract + +`auths-proof` publishes one checksummed documentation-contract artifact per +release candidate. It contains or references: + +- release, semantic, protocol, ABI, and package identities; +- supported runtimes and SDK versions; +- the cross-language capability matrix; +- Rust, TypeScript, and Python public symbol exports; +- runtime route and content-type contracts; +- profile identities, limits, and stable outcomes; +- stable error registry; +- canonical example and adversarial fixtures; +- assurance-claim and evidence indexes; and +- source repository links pinned to the release commit. + +The artifact contains facts, not marketing prose. A typed parser in the docs +repository rejects unknown contract versions, missing required sections, +duplicate semantic identities, malformed limits, and integrity mismatch before +content generation begins. + +The top-level artifact is `auths-docs-contract-v1.json`. Its records use stable +semantic identities rather than presentation names or URLs. The central join +key is an operation identity such as: + +```text +auths.operation.authority.create/1 +``` + +An operation record may project to a Rust item, TypeScript export, Python +symbol, runtime endpoint, profile operation, errors, examples, and evidence. +The join never depends on a display label, function name, URL slug, source line, +or documentation heading. + +Each SDK owns a small checked projection manifest: + +```yaml +operation: auths.operation.authority.create/1 +language: typescript +package: "@auths-dev/sdk" +symbol: createAuthority +entrypoint: auths +``` + +The manifest maps semantic identity to a public symbol. It does not repeat the +symbol's arguments, return type, documentation, or availability; those facts +come from the compiled public artifact. Missing symbols, duplicate mappings, +unmapped public operations, and mappings to private symbols fail CI. + +### 13.5 Public-surface extraction + +Reference facts are extracted from what users actually install, not inferred +from source layout: + +- **Rust:** a pinned docs-only nightly emits rustdoc JSON for the released + public crates. A pinned parser using the matching `rustdoc-types` schema + converts it to the documentation contract. This nightly is build tooling + only; it does not change the product's stable toolchain or MSRV. +- **TypeScript:** packed npm artifacts are installed into an empty consumer. + `@microsoft/api-extractor` reads their emitted `.d.ts` files and produces a + normalized API model. +- **Python:** built wheels are installed into an empty virtual environment. + Griffe reads the installed runtime package and its `.pyi` typing contract; + the extractor rejects disagreement between runtime exports and typed public + exports. +- **Runtime API:** endpoints are not scraped from Axum source. Every public + route is declared through a typed, Rust-owned `RuntimeEndpointSpec` beside + the concrete handler. The route registry and docs exporter consume the same + descriptor, and a completeness test rejects a public route without a spec or + a spec without a registered route. +- **Profiles, errors, limits, and evidence:** existing typed registries, + semantic-freeze identities, fixtures, and assurance manifests export their + data into the same contract. + +`RuntimeEndpointSpec` contains only public contract metadata: stable operation +and page identities, method, path, request and response schemas, outcomes, +stable error identities, authentication and trust-boundary requirements, +profile, maturity, and limits. It does not introduce a generic runtime router +or weaken the repository's concrete profile boundary. + +The generation pipeline is one-way: + +```text +installed packages + runtime/profile registries + fixtures + | + v + surface-specific extractors + | + v + parsed AuthsDocsContract (stable identities) + | + v + completeness + cross-language joins + | + v + typed ReferencePageModel + / | \ + v v v + HTML canonical .md search/manifest +``` + +No generated output may become an input to another extractor. Every fact has a +single provenance record back to an installed artifact, Rust-owned registry, +or fixture. + +### 13.6 Stable page mapping and content dependencies + +Every public page has a stable `page_id`. Generated operation pages normally +derive it from the operation identity, while human pages declare it in +frontmatter. URLs are presentation and may change; page identities do not. + +Human MDX links to generated facts with typed components: + +```mdx + + + +``` + +The build resolves these identities to release-specific URLs and content. +Authors do not hardcode reference slugs, copy signatures, or paste examples. + +Frontmatter also declares semantic dependencies: + +```yaml +uses: + operations: [auths.operation.authority.create/1] + profiles: [auths.profile.rest-effect/1] + errors: [auths.error.replay_detected/1] + scenarios: [rest-authorize-v1] +``` + +The dependency graph makes a contract diff actionable. If an operation, +profile, error, or scenario changes, the originating pull request lists every +human page whose meaning may need review. The generated facts update +automatically; security or explanatory prose remains human-reviewed. + +### 13.7 Exact change propagation + +When a function argument changes: + +1. the SDK is built and installed into an empty consumer; +2. its extractor observes the new compiled signature and changes the contract + fingerprint for the same stable operation identity; +3. existing public-API and semantic-version gates classify the change; +4. the reference page renders the new argument automatically—there is no + parameter table to edit; +5. every executable scenario using the function is compiled or run and fails + at its real call site if it needs an update; +6. the dependency graph identifies authored pages that use the operation; +7. a docs preview shows the exact reference and guide diff; and +8. the code pull request cannot merge until the contract, examples, affected + page review, and preview are consistent. + +When an API endpoint is added: + +1. the concrete handler is added with a `RuntimeEndpointSpec` containing stable + operation and page identities; +2. the route-completeness test fails if either the handler or descriptor is + absent; +3. the release contract exports the endpoint; +4. the runtime API page, navigation entry, search record, Markdown twin, and + reference manifest are generated automatically; +5. stable or launch endpoints must declare schemas, outcomes, errors, trust + boundary, limits, and at least one executable scenario; and +6. CI fails until all required coverage exists. + +When a surface is removed or renamed before launch, Auths performs a direct +cutover. Stale mappings, links, examples, and semantic dependencies fail in the +same pull request. Compatibility aliases, redirects, and deprecation pages are +not created for unpublished surfaces. After 1.0, versioned release contracts +preserve the old reference under its supported release path. + +### 13.8 Cross-repository preview and release flow + +Separate repositories must not turn documentation into an eventually +consistent afterthought. A public-surface pull request in `auths-proof` runs: + +```text +auths-proof PR + -> build packed SDKs, wheels, crates, fixtures, and runtime metadata + -> cargo xtask docs-contract + -> sign/checksum one immutable PR artifact + -> invoke the auths-proof-docs reusable preview workflow by pinned SHA + -> install the artifact in an isolated checkout + -> build reference, execute examples, render site, publish preview + -> return one required "Documentation contract and preview" check +``` + +The invocation passes an immutable artifact digest and source commit, never a +mutable sibling checkout or branch name. Automatic contract-diff +classification decides whether the check is required; a label cannot suppress +it. + +After merge, the release candidate publishes the same versioned contract +bundle. An automation opens or updates a docs-repository release pull request +pinned to its digest. Final package promotion and the stable docs deployment +require the docs qualification result for that exact digest. The deployed site +records the product commit, docs commit, package versions, contract version, +and artifact digest, so a previous static bundle can be restored exactly. + +## 14. Content and component contracts + +Every human-authored page has typed frontmatter: + +```yaml +id: start.rest-api +title: Protect a REST effect +description: Give one caller authority for one exact application action. +audience: application-developer +depth: start +status: stable +languages: [rust, typescript, python] +products: [sdk, runtime] +release: inherited +reviewers: [sdk, security] +uses: + operations: [auths.operation.authority.create/1] + profiles: [auths.profile.rest-effect/1] + errors: [] + scenarios: [rest-authorize-v1] +``` + +The parser accepts a closed set of identifiers. Unknown audience, depth, +status, language, product, or semantic dependency values fail the build. + +The component system includes: + +- `GlobalHeader`, `ContextNavigation`, `PageOutline`, and `ReferenceShell` for + the two-row header and edge-aligned, collapsible documentation geometry; +- `OutcomeHero` for a concrete reader result; +- `LanguageGroup` for synchronized language panels; +- `CodeBlock` and `CodeBlockWithResult` for language-aware source, Bash + overrides, and typed normalized results; +- `TestedExample` for source-linked executable code; +- `FiveVerbFlow` and `FiveNounMap` for the simple model; +- `OutcomeMatrix` for completed, denied, indeterminate, recoverable, verified, + and rejected results; +- `TrustBoundary` for trusted and untrusted inputs; +- `Lifecycle` for state transitions without implying false success; +- `ReceiptView` for safe summary, authorized detail, and opaque views; +- `ProfileContract` for exact-effect documentation; +- `ReferenceSymbol` for generated signatures and types; +- `ReferenceLink` and `ReferenceSignature` for stable identity-based reference + resolution without hardcoded URLs or copied declarations; +- `SecurityCallout`, `FailurePath`, and `OperationalCallout`; +- `VersionBadge` and `AvailabilityBadge`; +- `Diagram` with accessible text equivalent; and +- `PageActions` and `SectionActions` for page/section Markdown, source, prompt, + and issue actions. + +Components may standardize presentation. They must not generate profile +semantics, infer retry behavior, or convert denial into indeterminate. + +## 15. Versioning and release behavior + +Before launch, the site follows direct cutovers and does not preserve obsolete +prelaunch surfaces with deprecation pages or compatibility aliases. At public +1.0: + +- `/` and unversioned paths describe the latest stable release; +- `/v//...` preserves supported release documentation; +- `/next/...` documents the main-branch candidate with a permanent warning; +- every page shows its selected release and SDK package versions; +- code examples install exact compatible major/minor versions while allowing + patch selection according to the support policy; and +- links between versions never silently cross from stable to `next`. + +A release cannot publish until its documentation-contract artifact, generated +reference, examples, links, Markdown twins, and support matrix pass together. + +## 16. Security, privacy, and accessibility + +- Examples use obvious placeholders or deterministic public fixture material. + Secret scanners run against authored content, generated output, build logs, + and deployment bundles. +- Copy actions never include environment values, cookies, account identifiers, + or analytics context. +- The site uses a restrictive content security policy and does not execute + third-party scripts by default. +- Search is local for the first release. If hosted search is introduced later, + query collection requires an explicit privacy decision. +- Code examples must distinguish public identity material, opaque authority, + secret custody material, and authorized disclosure. +- Receipt examples default to bounded summaries. Sensitive detail appears only + in pages explicitly teaching authorized disclosure. +- Focus, heading order, landmarks, tab semantics, contrast, reduced motion, + zoom, and code scrolling are tested automatically and manually. +- Diagrams have text equivalents in HTML and Markdown. +- No essential instruction depends only on hover, animation, color, or a + desktop-sized viewport. + +## 17. APIs + +The first release is statically served and exposes no mutable application API. +Its public read contract is: + +```text +GET / canonical HTML +GET /.md canonical Markdown +GET //sections/
.md bounded canonical section Markdown +GET /llms.txt concise machine index +GET /llms-full.txt bounded essential corpus +GET /.well-known/auths-docs.json release and discovery metadata +GET /search-index.json static search catalog +GET /reference/manifest.json release-scoped reference identities +GET /sitemap.xml canonical route catalog +``` + +Build tools operate through typed local interfaces: + +```text +fetchRelease(release_or_digest) -> VerifiedReleaseBundle +extractRust(bundle) -> RustSurface +extractTypeScript(bundle) -> TypeScriptSurface +extractPython(bundle) -> PythonSurface +parseDocsContract(bundle, surfaces) -> VerifiedDocsContract +buildPageModel(contract, authored_pages) -> VerifiedPageGraph +buildReference(page_graph) -> GeneratedReference +loadScenario(id) -> Scenario +verifyExample(language, scenario, release) -> NormalizedOutcome +renderHtml(page_graph) -> StaticHtml +renderMarkdown(page_graph) -> CanonicalMarkdown +buildSearch(page_graph) -> SearchIndex +``` + +Only `VerifiedDocsContract` may feed generated reference. Integrity checking, +contract-version parsing, and schema parsing occur before generation. + +## 18. Implementation epics + +Implement the following detailed epics in order. Each file follows the +implementation-spec house style used by AP-SPEC-038: zero-context starting +point, architecture, APIs, files, task checklist, adversarial tests, validation +commands, and an objective exit gate. + +```text +auths-proof foundations + Epic 1 contract/identities + | + Epic 2 source docs --------+ + | | + Epic 3 product facts ------+ + | | + Epic 4 installed bundle <--+ + | +auths-proof-docs product + Epic 5 site/MDX foundation + | + Epic 6 progressive journey + | + Epic 7 executable examples + | + Epic 8 generated reference + | + Epic 9 deep guidance + | + Epic 10 machine surfaces + | + Epic 11 cross-repo qualification and release +``` + +1. [Freeze the documentation surface contract](0040/epic_1.md): establish + stable operation, page, scenario, and SDK projection identities. +2. [Make the public API self-documenting at source](0040/epic_2.md): document + public Rust, TypeScript, and Python surfaces by product priority and enforce + installed documentation quality without incentivizing private-comment + noise. +3. [Export runtime, profile, error, and assurance facts](0040/epic_3.md): make + non-SDK product facts Rust-owned and machine-readable from the same sources + that build the runtime. +4. [Extract installed SDK surfaces and publish the docs + bundle](0040/epic_4.md): extract packaged crates, npm declarations, and + wheel runtime/stub surfaces and join them through stable identities. +5. [Build the static docs foundation and MDX contract](0040/epic_5.md): create + the constrained Vinext/Vite/MDX product and shared HTML/Markdown model. +6. [Ship the progressive product journey](0040/epic_6.md): deliver the five- + verb fifteen-minute path and outcome-first information architecture. +7. [Build executable cross-language examples](0040/epic_7.md): run and compare + every displayed Rust, TypeScript, and Python launch scenario. +8. [Generate the deep reference from stable identities](0040/epic_8.md): build + operation, symbol, endpoint, profile, error, lifecycle, receipt, protocol, + and assurance reference without checked-in generated MDX. +9. [Publish architecture, operations, integrations, and + assurance](0040/epic_9.md): complete the deep human guidance and open-core + runbooks. +10. [Deliver machine-readable and agent-first + documentation](0040/epic_10.md): ship canonical Markdown, indexes, + discovery, and an optional isolated read-only docs MCP. +11. [Enforce cross-repository qualification and release](0040/epic_11.md): + make current-head documentation previews and immutable deployment part of + the originating product change and release gate. + +## 19. CI and quality gates + +The maintainability guarantee begins in the repository that changes the public +surface. Every `auths-proof` pull request runs a lightweight contract-diff job +after its public artifacts build. If the fingerprint is unchanged, the docs +preview is optional. If it changes, CI automatically requires: + +- installed-artifact extraction for each affected language; +- runtime route/spec completeness where runtime code changed; +- semantic operation and SDK projection completeness; +- public-API and version classification; +- regeneration and validation of the PR documentation contract; +- compilation or execution of affected examples; +- an affected-page report from semantic dependencies; and +- the digest-pinned `auths-proof-docs` preview result. + +There is no manually applied `docs-not-required` label. A pull request cannot +claim that a public change is internal while the compiled contract says +otherwise. + +Every pull request or invoked preview in `auths-proof-docs` runs: + +- exact toolchain, lockfile, and immutable artifact checks; +- strict TypeScript, content-schema parsing, and MDX policy validation; +- release-artifact integrity, provenance, and contract-version checks; +- missing, duplicate, stale, or unmapped operation/page/symbol/route checks; +- generated reference and semantic-dependency graph checks; +- Rust, TypeScript, and Python executable example tests for affected scenarios; +- cross-language normalized-outcome comparison; +- rejection of copied signatures, parameter tables, endpoint inventories, and + executable example fences in authored MDX; +- internal, external, anchor, stable-identity, source, and Markdown-twin link + checks; +- secret and sensitive-fixture scanning; +- spelling and preferred-vocabulary checks; +- static-search and synonym-index checks; +- HTML validation; +- Playwright interaction and responsive tests; +- axe accessibility checks; +- deterministic screenshot comparisons for the home, guide, SDK reference, + and runtime API reference templates at maintained desktop, tablet, narrow + mobile, and 200-percent-zoom viewports; +- expanded/collapsed contextual navigation, two-row header alignment, centered + search, sticky code-rail, and anchor-offset tests; +- synchronized Rust/TypeScript/Python selection plus Bash-override and JSON + result-highlighting tests; +- Lighthouse budgets; +- sitemap, `llms.txt`, discovery, and reference-manifest checks; and +- a production-equivalent static deployment smoke test. + +Generated reference output is not committed, so "drift" means disagreement +between schemas, mappings, installed artifacts, and rendered outputs—not a bot +rewriting thousands of checked-in pages. A compact contract fingerprint and +public-surface snapshot may remain in `auths-proof` for semantic diffing. + +Nightly CI checks external links, all supported documentation versions, all +examples, and dependency vulnerabilities. Release CI runs the complete matrix +against the exact candidate packages and reference service, then records both +repository commits and the contract digest in the deploy manifest. + +Flaky docs tests are defects. They may be quarantined only with an owner, +issue, expiration date, and no reduction in security or example-parity +coverage. + +## 20. Content governance + +Each public page has one owning area and required reviewers. Security claims, +protocol reference, profile semantics, and operational instructions require a +reviewer from the corresponding code ownership area. + +Three source classes are allowed: + +1. **Authored:** `.mdx` narrative, guides, architecture, and operations + content using only allowlisted components. +2. **Generated:** signatures, routes, profiles, errors, limits, versions, and + evidence facts from the release contract. +3. **Executable:** examples whose source is run in CI and embedded directly. + +Generated facts must not be hand-edited. Authored prose must not restate exact +signatures, limits, or support matrices that the release contract can supply. +Executable code must not be copied into authored fences. + +An automated freshness report lists pages whose owning public contract changed +since their last review. Freshness is a review signal, not permission for an +LLM to rewrite security claims automatically. + +## 21. Explicit non-goals + +The first release does not include: + +- an authenticated customer dashboard; +- enterprise organization or fleet administration; +- a writable documentation MCP server; +- a general-purpose AI chat widget; +- a runtime CMS or documentation database; +- arbitrary in-browser execution against customer infrastructure; +- hidden compatibility pages for superseded prelaunch APIs; +- separate TypeScript or Python definitions of Auths semantics; +- automatic publication of every file under `docs/`; or +- claims that are not linked to release-scoped evidence. + +## 22. Completion condition + +AP-SPEC-040 is complete when Auths has one public documentation experience in +which: + +- a newcomer reaches a safe first effect in fifteen minutes; +- the five-verb surface remains simple and prominent; +- Rust, TypeScript, and Python examples are idiomatic, switchable, executable, + and semantically equal; +- architecture, operations, profiles, protocol, and assurance depth are easy + to find without burdening the quickstart; +- every public surface is release-scoped and generated from verified facts; +- HTML and Markdown deliver the same meaning; +- search works for human language and exact technical identities; +- the site is accessible, fast, private by default, and statically + self-hostable; and +- no website convenience can change, widen, or ambiguously describe Auths + authorization semantics. + +The desired result is not merely attractive documentation. It is an interface +that makes a new authority layer legible enough to adopt, precise enough to +trust, and structured enough for humans and agents to use without inventing +their own interpretation. diff --git a/docs/specs/0040/README.md b/docs/specs/0040/README.md new file mode 100644 index 00000000..14089225 --- /dev/null +++ b/docs/specs/0040/README.md @@ -0,0 +1,97 @@ +# AP-SPEC-040 Execution Map + +AP-SPEC-040 has two coordinated implementation lanes and one release gate: + +- **Platform epics (`P1`–`P11`)** build source truth, extraction, typed page + models, rendering, executable examples, and qualification machinery. +- **Content epics (`C0`–`C9`)** choose reader journeys and author the public + explanations, guidance, curation, and conceptual diagrams. +- **The verified page graph** is the only input to HTML, Markdown, search, + navigation, and agent-readable output. + +The lanes are not independent documentation systems. Content Epic 0 defines +their ownership contract and blocks all public-content implementation. + +## Non-overlap rule + +```text +auths-proof product facts auths-docs editorial sources +signatures, routes, errors explanations, choices, journeys +profiles, limits, evidence conceptual diagrams, curation +tested scenario artifacts references to scenario identities + \ / + \ / + +-- strict compiler --+ + | + v + VerifiedPageGraph + / | | \ + HTML Markdown Search LLM +``` + +If changing released software could make a statement false, that statement is +a generated fact or tested scenario. Editorial content refers to it by stable +identity and does not copy it. + +## Platform epics + +| ID | Epic | Responsibility | +|---|---|---| +| P1 | [Freeze the documentation surface contract](./epic_1.md) | Stable semantic joins | +| P2 | [Make the public API self-documenting](./epic_2.md) | Source-owned public documentation | +| P3 | [Export runtime and assurance facts](./epic_3.md) | Non-SDK product facts | +| P4 | [Publish the immutable docs bundle](./epic_4.md) | Installed-artifact extraction | +| P5 | [Build the static docs foundation](./epic_5.md) | MDX, design system, page compiler | +| P6 | [Build journey composition contracts](./epic_6.md) | Typed editorial composition primitives | +| P7 | [Build executable examples](./epic_7.md) | Tested cross-language scenarios | +| P8 | [Generate deep reference](./epic_8.md) | Generated fact pages | +| P9 | [Build deep-content composition contracts](./epic_9.md) | Architecture, operations, integration, and assurance components | +| P10 | [Deliver machine-readable documentation](./epic_10.md) | HTML-adjacent machine projections | +| P11 | [Enforce qualification and release](./epic_11.md) | Cross-repository CI and deployment | + +## Content epics + +The editorial lane is indexed in [content/README.md](./content/README.md). +Content Epic 0 must complete first. + +## Combined execution order + +```text +P1 -> P2/P3 -> P4 -> P5 + | | + +------------------> C0 + | + +----+----+ + v v + P6 C1-C3 + | | + +----+----+ + v + P7 + C4 + | + P8 + C5 + | + P9 + C6-C9 + | + P10 + | + P11 +``` + +Platform primitives may be implemented using bounded fixture content before +their corresponding editorial epic is complete. Fixture prose must be visibly +synthetic and must not become an accidental public corpus. + +## Completion rules + +- A platform epic cannot author or approve public narrative. +- A content epic cannot define extractors, generated facts, rendering forks, + or CI orchestration. +- Generated reference pages are never hand-edited. +- Displayed executable code comes from a qualified scenario artifact. +- Authored MDX declares stable dependencies in frontmatter. +- All outputs are projections of one `VerifiedPageGraph`. +- A cross-lane change is split into a platform commit and a content commit when + ownership crosses repositories; their immutable artifact identities join + them without mutable sibling dependencies. + diff --git a/docs/specs/0040/content/PROPOSED_SITE_HIERARCHY.md b/docs/specs/0040/content/PROPOSED_SITE_HIERARCHY.md new file mode 100644 index 00000000..74c4c070 --- /dev/null +++ b/docs/specs/0040/content/PROPOSED_SITE_HIERARCHY.md @@ -0,0 +1,230 @@ +# Proposed Auths Documentation Hierarchy + +## Routing rule + +Every public page has one primary owner among the six top-level sections. Its +canonical route begins with that section's prefix. Cross-topic links are +allowed only inside an explicitly labelled **Related topics** block; they are +never used as a substitute for the current section's missing content. + +Reference and Assurance are cross-cutting utilities. They keep their own +namespaces and navigation, but every primary section links to the exact utility +page it needs—not to a generic utility landing. + +## 1. Get started + +```text +/get-started landing and path chooser +├── /prerequisites supported runtimes and inputs +├── /choose deterministic integration chooser +├── /quickstarts tested-project index +│ ├── /local-rest-effect first in-process effect +│ ├── /runtime-effect first HTTPS runtime effect +│ ├── /agent-delegation first delegated tool +│ ├── /approved-plan first exact approved plan +│ ├── /offline-verification first effect-free verification +│ ├── /recovery first recoverable execution +│ └── /identity-swap first cryptographic-suite swap +├── /paths outcome-path index +│ ├── /application protect an application effect +│ ├── /agent delegate to an agent +│ ├── /runtime deploy the runtime boundary +│ ├── /verification verify without executing +│ └── /cross-company independent organizations +├── /evaluate deterministic evaluation plan +└── /adoption incremental-adoption index + ├── /plan privacy-safe inventory + ├── /signed-requests compose existing signatures + ├── /oauth-oidc retain login/session identity + ├── /api-keys close ambient credentials + ├── /cloud-iam compose workload IAM + ├── /policy-engines compose Cedar/OPA/ReBAC + ├── /capabilities bridge UCAN/Biscuit/macaroons + ├── /approvals bind existing approval systems + ├── /shadow-mode compare without effects + └── /cutover enforce and roll back one effect +``` + +Left-nav groups: **Choose a path**, **Quickstarts**, **Adopt incrementally**, +**Next steps**. + +## 2. Identity & trust + +```text +/identity-trust landing +├── /how-it-works identity versus authority tour +├── /identity-sources source chooser +│ ├── /raw-public-keys standalone labelled key evidence +│ ├── /oauth-oidc user/session identity +│ ├── /spiffe workload identity +│ └── /application-resolvers application-owned resolution +├── /cryptographic-suites suite chooser +│ ├── /ed25519 maintained adapter +│ ├── /p256 maintained proof of agility +│ └── /custom-and-post-quantum application adapters and limits +├── /trust-policy roots, issuers, and assurance +├── /exchange-public-identity transport-neutral exchange +├── /key-and-root-rotation overlap, rollback, recovery +├── /verification-context exact trusted-context inputs +└── /testing unknown suite, wrong root, mismatch +``` + +Left-nav groups: **Understand**, **Identity sources**, **Cryptography**, +**Operate trust**, **Test**. + +## 3. Authority + +```text +/authority landing +├── /model actor/action/authority/outcome/receipt +├── /create author exact authority +├── /constraints action, resource, time, use, budget +├── /delegate attenuation and critical extensions +│ ├── /depth-and-chain multi-hop boundaries +│ └── /widening-failures adversarial cases +├── /lifecycle lifecycle index +│ ├── /validity-and-expiry temporal bounds +│ ├── /revocation-and-status lifecycle evidence +│ ├── /uses-and-replay exact-use accounting +│ └── /budgets budget algebra and state +├── /plans ordered plan semantics +│ └── /approvals transaction-bound approvals +├── /execute sealed command and closed gateway +├── /resume recovery without fresh retry +├── /verify effect-free verification +├── /receipts evidence model +│ └── /disclosure opaque, summary, authorized full +└── /profiles domain semantics and profile kit +``` + +Left-nav groups: **Model**, **Author and narrow**, **Lifecycle**, **Execute and +recover**, **Verify and inspect**, **Profiles**. + +## 4. Agents + +```text +/agents landing and use-case chooser +├── /how-auths-works agent-specific architecture +├── /quickstart executable one-tool delegation +├── /delegation exact scope and prohibited action +├── /approved-plans multi-party exact plan +├── /multi-agent attenuated handoffs +├── /mcp MCP index +│ ├── /client use Auths from an agent harness +│ ├── /protect-server closed execution for MCP tools +│ ├── /tool-profiles canonical tool actions +│ └── /transport-boundary MCP success is not authority +├── /identity agent/workload identity composition +├── /skills-and-plugins maintained tooling and provenance +├── /production-patterns state, custody, gateway ownership +└── /testing widening, substitution, uncertainty +``` + +Left-nav groups: **Start**, **Delegate**, **MCP**, **Compose**, **Operate and +test**. + +## 5. Production operations + +```text +/operations landing and deployment chooser +├── /evaluate-locally production-shaped local exercise +├── /deploy-runtime deployment topology and readiness +├── /configure configuration index +│ ├── /durable-state replay/use/budget/recovery store +│ ├── /custody KMS/HSM/application signer +│ ├── /trust-and-profiles roots, suites, profiles +│ └── /provider-gateways closed credential boundary +├── /observability metrics, logs, traces, redaction +├── /execution-lifecycle state-machine tour +├── /recovery-and-reconciliation retry/resume/reconcile decision tree +├── /backup-and-restore semantic restore exercise +├── /upgrade-and-rollback exact release promotion +├── /receipt-retention retention and bounded disclosure +├── /security-checklist deployment hardening +└── /incidents runbook index + ├── /state-loss fence, restore, reconcile + ├── /signer-outage preserve verification-only paths + ├── /trust-root-error rollback and re-evaluate + ├── /provider-unknown stop fresh retry, reconcile + ├── /receipt-disclosure contain without deleting evidence + └── /compromised-credential revoke, rotate, reconcile +``` + +Left-nav groups: **Deploy**, **Configure**, **Observe**, **Recover**, **Maintain**, +**Incident response**. + +## 6. Developers + +```text +/developers landing +├── /quickstarts developer-oriented catalog/index +├── /sdks SDK chooser +│ ├── /rust native SDK orientation +│ ├── /typescript product SDK orientation +│ ├── /python product SDK orientation +│ └── /parity shared operation/outcome mapping +├── /runtime-api Runtime API orientation +├── /cli CLI orientation and installation +├── /testing fixture and outcome catalog +├── /errors closed-outcome and error hub +├── /versioning prelaunch and release contracts +├── /integrations composition index +│ ├── /identity-and-trust OIDC, SPIFFE, keys, resolvers +│ ├── /policy Cedar, OPA, ReBAC +│ ├── /cloud-iam provider identity and credentials +│ ├── /transport HTTPS, Iroh, queues +│ ├── /capabilities UCAN, Biscuit, macaroons +│ └── /profile-kit application-owned profiles +├── /extension-kits ports, adapters, conformance +├── /examples source-at-release catalog +└── /releases changelog and support matrix +``` + +Left-nav groups: **Start building**, **SDKs**, **Runtime and CLI**, **Test and +debug**, **Integrate and extend**, **Releases**. + +## Cross-cutting utility hierarchies + +These do not compete with the six product sections. They are exact lookup and +evidence destinations. + +```text +/reference +├── /sdk +│ ├── /rust +│ ├── /typescript +│ └── /python +├── /runtime-api +├── /cli +├── /profiles +├── /errors +├── /schemas +├── /evidence +└── /manifest.json + +/assurance +├── /semantics +├── /authority +├── /execution +├── /disclosure +├── /cross-language +├── /formal +├── /adversarial +├── /supply-chain +└── /limitations +``` + +## Required page relationships + +Every non-landing page renders: + +1. global top navigation; +2. the complete left navigation for its owning section; +3. breadcrumbs from section landing to current page; +4. previous and next pages within its local sequence; +5. page and section Markdown actions; +6. related topics, explicitly labelled as cross-topic; +7. source/release/scenario provenance where applicable; and +8. a next action that remains in the owning section unless the journey is + complete. + diff --git a/docs/specs/0040/content/README.md b/docs/specs/0040/content/README.md new file mode 100644 index 00000000..976b0d56 --- /dev/null +++ b/docs/specs/0040/content/README.md @@ -0,0 +1,96 @@ +# AP-SPEC-040 Content Epics + +These epics turn the research in +[`STRIPE_CONTENT_RESEARCH.md`](./STRIPE_CONTENT_RESEARCH.md) into an executable +content program for Auths documentation. They run as the editorial lane beside +AP-SPEC-040 Platform Epics P1–P11. The platform lane builds source truth, +generation, components, and release qualification. This lane chooses reader +journeys and authors the public explanation that occupies those components. + +[Content Epic 0](./epic_0.md) is the binding ownership contract. If another +epic appears to contradict it, Epic 0 wins until the specs are reconciled. + +The rendered-site audit in +[`SITE_CONTENT_AND_LINK_AUDIT.md`](./SITE_CONTENT_AND_LINK_AUDIT.md) revoked the +completion status of Content Epics 1–9. Their first implementation produced +useful primitives and fixtures but did not satisfy coherent hierarchy, +topic-local navigation, content depth, or link-intent requirements. Do not +check them off again until Content Epics 10–19 qualify the resulting site. + +## Execution order + +| Order | Epic | Dependency | Exit result | +|---:|---|---|---| +| 0 | [Platform and editorial ownership](./epic_0.md) | P1 and P5 contracts | Facts, scenarios, and narrative have non-overlapping owners | +| 1 | [Global information architecture and topic landings](./content_epic_1.md) | C0, P5–P6 | Every durable domain has a landing and contextual tree | +| 2 | [Getting started and integration chooser](./content_epic_2.md) | C0–C1, P6 | A new reader reaches the right first build path | +| 3 | [Semantic tours and lifecycle concepts](./content_epic_3.md) | C0–C1, P6 | Readers understand Auths before reading reference | +| 4 | [Outcome quickstarts and tested projects](./content_epic_4.md) | C0, C2–C3, P7 | Each recommended path works end to end | +| 5 | [Developer resources and generated reference](./content_epic_5.md) | C0, P4 and P8 | SDK, Runtime API, CLI, error, and version surfaces are complete | +| 6 | [Agents, MCP, and integrations](./content_epic_6.md) | C0, C3–C5, P9 | Agent and composition paths are understandable and independent | +| 7 | [Adoption and migration](./content_epic_7.md) | C0, C2–C6, P9 | Existing systems can adopt Auths incrementally | +| 8 | [Operations, testing, failure, and recovery](./content_epic_8.md) | C0, C4–C7, P9 | Teams can run Auths and respond safely | +| 9 | [Assurance narrative and governance](./content_epic_9.md) | C0–C8, P9 | Claims remain evidenced, current, searchable, and usable | +| 10 | [Canonical information architecture](./content_epic_10.md) | Audit, C0 | Every page has one section, parent, and canonical route | +| 11 | [Topic shell and page-type contracts](./content_epic_11.md) | C10, P5–P6 | Navigation and content depth are enforced universally | +| 12 | [Rebuild Get started](./content_epic_12.md) | C10–C11, P7 | First journeys are executable and coherent | +| 13 | [Complete Identity and trust](./content_epic_13.md) | C10–C12 | Identity remains agnostic and independently usable | +| 14 | [Complete Authority](./content_epic_14.md) | C10–C13 | Five verbs progressively disclose full authority semantics | +| 15 | [Complete Agents and MCP](./content_epic_15.md) | C10–C14 | Agent and MCP journeys are executable and self-contained | +| 16 | [Complete Production operations](./content_epic_16.md) | C10–C15 | Operators receive tested procedures and runbooks | +| 17 | [Complete Developers and integrations](./content_epic_17.md) | C10–C16 | Build, test, integrate, and extend paths are complete | +| 18 | [Complete Reference and Assurance](./content_epic_18.md) | C10–C17, P8–P10 | Exact lookup and evidence utilities are complete | +| 19 | [Full-site qualification](./content_epic_19.md) | C10–C18, P11 | Orphans, shallow pages, and misleading links fail CI | + +Only one content epic is in progress at a time. Update the checkbox in this +README only after every acceptance criterion in the epic passes. + +## Progress + +- [x] Content Epic 0 — Platform and editorial ownership +- [ ] Content Epic 1 — Global information architecture and topic landings +- [ ] Content Epic 2 — Getting started and integration chooser +- [ ] Content Epic 3 — Semantic tours and lifecycle concepts +- [ ] Content Epic 4 — Outcome quickstarts and tested projects +- [ ] Content Epic 5 — Developer resources and generated reference +- [ ] Content Epic 6 — Agents, MCP, and integrations +- [ ] Content Epic 7 — Adoption and migration +- [ ] Content Epic 8 — Operations, testing, failure, and recovery +- [ ] Content Epic 9 — Assurance narrative and governance +- [x] Content Epic 10 — Canonical information architecture and route ownership +- [x] Content Epic 11 — Topic shell, left navigation, and page-type contracts +- [x] Content Epic 12 — Rebuild Get started as an executable journey +- [x] Content Epic 13 — Complete Identity and trust documentation +- [x] Content Epic 14 — Complete Authority documentation +- [x] Content Epic 15 — Complete Agents and MCP documentation +- [x] Content Epic 16 — Complete Production operations documentation +- [x] Content Epic 17 — Complete Developer, integration, and extension documentation +- [x] Content Epic 18 — Complete Reference and Assurance utilities +- [x] Content Epic 19 — Full-site content and link qualification + +## Zero-context agent prompt + +```text +Work through AP-SPEC-040 content epics in docs/specs/0040/content/README.md. + +Before implementation: +1. Read docs/specs/0040-stripe-quality-documentation-platform.md. +2. Read docs/specs/0040/README.md and content/epic_0.md completely. +3. Read completed AP-SPEC-040 platform epics. +4. Read docs/specs/0040/content/STRIPE_CONTENT_RESEARCH.md. +5. Read the current content epic completely. +6. Inspect both auths-proof and the independent auths-docs repository. + +Rules: +- Auths-owned semantic facts come from immutable release artifacts. +- Treat every public block as generated fact, tested scenario, or editorial + narrative; never give one block multiple owners. +- Do not copy Stripe wording, taxonomy, or visual identity. +- Do not hand-author SDK signatures, endpoint inventories, errors, versions, + evidence status, or executable code represented as tested. +- Keep Rust, TypeScript, and Python semantically identical and idiomatic. +- Preserve progressive disclosure and security boundaries. +- Every public page requires canonical Markdown. +- Run the epic validation commands and record evidence before checking it off. +- One content epic is one focused commit in each repository it changes. +``` diff --git a/docs/specs/0040/content/SITE_CONTENT_AND_LINK_AUDIT.md b/docs/specs/0040/content/SITE_CONTENT_AND_LINK_AUDIT.md new file mode 100644 index 00000000..f01a6d44 --- /dev/null +++ b/docs/specs/0040/content/SITE_CONTENT_AND_LINK_AUDIT.md @@ -0,0 +1,321 @@ +# Auths Documentation Content and Link Audit + +**Audit date:** 2026-08-14 +**Rendered target:** `http://localhost:3000` +**Scope:** every registered public page and every internal link inside each +page's `
` content. Global header and footer links are assessed separately +by the site-shell qualification suite. + +## Verdict + +The current documentation has a credible visual prototype and a useful +content-ownership foundation, but it is not yet a coherent documentation +product. The landing pages look organized while the next click frequently +drops the reader into a shallow, context-free page. The site currently models +pages as isolated records; it does not model a reader's durable place inside a +topic. + +This is a structural failure, not a copy-editing problem. + +The implementation of Content Epics 1–9 must not continue as additive page +creation. The site first needs a canonical hierarchy, topic-local navigation, +route ownership, content-depth contracts, and link-intent qualification. + +## Measured findings + +| Measure | Result | Meaning | +|---|---:|---| +| Registered HTML pages audited | 92 | Every page in the current content registries was rendered | +| Internal `
` links audited | 217 | Includes navigation, Markdown, section Markdown, and downloads | +| Navigational links | 109 | HTML destinations and topic transitions | +| Markdown links | 101 | Page and section machine-readable views | +| Download links | 7 | One per generated quickstart | +| Pages without any detected left navigation | 83 | Only 9 pages expose any left-side structure | +| Pages under 80 rendered words | 55 | Most new pages are labels plus one paragraph | +| Pages with no code block | 82 | Only SDK, Runtime API, quickstarts, and one REST guide contain code | +| Pages with at most one substantive destination | 68 | Most pages are dead ends after excluding their Markdown action | +| Navigational orphans | 60 | No other rendered page links to them after excluding self Markdown links | +| Broken HTML route targets | 0 | Routing works; relevance and hierarchy do not | +| Missing Markdown targets | 1 | `/reference/cli.md` is linked but absent | + +## Primary-section audit + +None of the six top-level sections has a topic-local left navigation. Links are +syntactically valid but often leave the section immediately. + +### Get started + +Current links: + +- `/get-started/choose` — related and inside the section; +- `/get-started/local` — related and inside the section; +- `/get-started/agent` — related and inside the section; +- `/get-started/verify` — related and inside the section; +- `/get-started/prerequisites` — related and inside the section; +- `/get-started/cross-company` — related and inside the section; and +- `/get-started/evaluate` — related and inside the section. + +The landing is the least misleading of the six, but its children have no +shared navigation, almost no code, and frequently hand off to legacy +`/start/*` or `/guides/*` pages. + +### Identity & trust + +Only `/identity-trust/how-it-works` descends into the section. The remaining +cards jump to generic destinations: + +- “Compose existing identity” → `/integrations`; +- “Keep adapters replaceable” → `/architecture`; +- “Turn identity into bounded action” → `/authority`; +- “Verify offline” → `/start/verify-receipt`; +- “Review agility claims” → `/assurance`; and +- “Open exact contracts” → `/reference`. + +These are potentially useful related links, but they are presented as if they +were the identity documentation itself. No page exists for raw keys, OIDC, +SPIFFE, application resolvers, suite selection, trust policy, key exchange, or +rotation. + +### Authority + +Only the lifecycle, approval-plan, and receipt pages live under `/authority`. +The landing sends its core verbs elsewhere: + +- “Create” and the recommended path → `/guides/protect-rest-effect`; +- “Delegate” → `/start/delegate-agent`; and +- “Execute and recover” → `/operations`. + +This makes Authority look like a label placed over unrelated pages. It has no +topic-local pages for the authority model, authoring, constraints, delegation, +use/budget bounds, revocation, verification, or profile semantics. + +### Agents + +Every substantive landing card leaves `/agents`: + +- “Delegate one tool” and “Delegate without widening” → + `/start/delegate-agent`; +- “Protect an effect” → `/guides/protect-rest-effect`; +- “Verify what happened” → `/start/verify-receipt`; +- “MCP and transports” → `/integrations`; +- “Agent identity” → `/identity-trust`; and +- “Closed execution” → `/operations`. + +The MCP link is materially misleading: the destination is a generic +integration overview with no MCP client or protected-server workflow. Seven +new `/agents/*` pages exist in the registry, but the landing does not link to +them; all seven are orphans and contain no code. + +### Production operations + +Only `/operations/execution-lifecycle` descends into the section. Other cards +jump to Runtime reference, Architecture, receipt starter content, Assurance, +or Developers. Eleven operational pages exist but ten are not linked by the +landing, most contain roughly 40–50 words, and none provides tested commands, +observations, stop conditions, or rollback steps. + +### Developers + +Every landing card leaves `/developers`: + +- SDKs → `/reference/sdk`; +- Runtime API → `/reference/runtime-api`; +- Quickstarts → `/guides/protect-rest-effect`; +- Integrations → `/integrations`; +- Agents and MCP → `/agents`; and +- Testing and evidence → `/assurance`. + +The SDK and Runtime destinations are technically useful, but the landing does +not lead through developer-owned index pages. The Quickstarts card is singular +and misleading: it promises a catalog and opens one legacy REST guide. Six +`/developers/*` pages and five secondary reference pages exist but are not +linked from the landing. + +## Page and link inventory + +The tables below cover every registered HTML page and every link rendered in +its main content. “MD” means the page's `View as Markdown` link to the same +route. “No topic nav” means either no left navigation or a legacy page-specific +nav that does not preserve the owning top-level section. + +### Home and legacy journey pages + +| Page | Main-content links | Audit | +|---|---|---| +| `/` | `/guides/protect-rest-effect` (four placements), `#model`, `/start/delegate-agent`, `/start/verify-receipt` | No topic nav; routes readers into legacy namespaces | +| `/guides/protect-rest-effect` | `/`, MD | Has code and a page-specific nav, but is a dead end outside the six-section hierarchy | +| `/start/delegate-agent` | MD, `/start/verify-receipt` | Legacy nav; zero code; not owned by Agents or Authority | +| `/start/verify-receipt` | MD, `/concepts` | Legacy nav; zero code; not owned by Identity, Authority, or Assurance | +| `/concepts` | `/concepts/index.md`, `/architecture` | Page-specific nav; dead end | +| `/concepts/auths-in-15-minutes` | MD, `/get-started/local`, `/reference/sdk` | No topic nav | +| `/architecture` | `/architecture/index.md`, `/operations` | Page-specific nav; dead end | +| `/architecture/trust-boundaries` | `/architecture/trust-boundaries/index.md` | Page-specific nav; dead end | + +### Get started and adoption + +| Page | Main-content links | Audit | +|---|---|---| +| `/get-started` | MD; `/get-started/choose`; `/local`; `/agent`; `/verify`; `/prerequisites`; `/cross-company`; `/evaluate` under the same prefix | No topic nav | +| `/get-started/choose` | MD, `/get-started/local` | Thin; chooser has no persistent section context | +| `/get-started/prerequisites` | MD only | Dead end; no code | +| `/get-started/local` | MD, `/guides/protect-rest-effect` | Hands off to legacy route; no code itself | +| `/get-started/runtime` | MD, `/guides/protect-rest-effect` | Wrong scenario destination; no runtime code | +| `/get-started/agent` | MD, `/start/delegate-agent` | Wrong namespace; no code | +| `/get-started/verify` | MD, `/start/verify-receipt` | Wrong namespace; no code | +| `/get-started/cross-company` | MD, `/start/delegate-agent`, `/start/verify-receipt` | Two generic handoffs; no cross-company workflow | +| `/get-started/evaluate` | MD, `/guides/protect-rest-effect`, `/start/delegate-agent`, `/start/verify-receipt` | Scenario index points only to legacy pages | +| `/get-started/adopt` | MD only | Orphan; dead end | +| `/adopt/plan` | MD only | Orphan; thin | +| `/adopt/signed-requests` | MD only | Orphan; thin | +| `/adopt/oauth-oidc` | MD only | Orphan; thin | +| `/adopt/api-keys` | MD only | Orphan; thin | +| `/adopt/cloud-iam` | MD only | Orphan; thin | +| `/adopt/policy-engines` | MD only | Orphan; thin | +| `/adopt/capabilities` | MD only | Orphan; thin | +| `/adopt/approvals` | MD, `/developers` | Orphan; tested-scenario link loses context | +| `/adopt/shadow-mode` | MD only | Orphan; thin | +| `/adopt/cutover` | MD only | Orphan; thin | + +### Identity and trust + +| Page | Main-content links | Audit | +|---|---|---| +| `/identity-trust` | MD, `/identity-trust/how-it-works`, `/integrations`, `/architecture`, `/authority`, `/start/verify-receipt`, `/assurance`, `/reference` | Six of seven content cards leave the section | +| `/identity-trust/how-it-works` | MD, `/identity-trust`, `/architecture/trust-boundaries` | No topic nav; conceptual only | +| `/integrations/identity-trust` | MD only | Orphan, thin, and outside Identity namespace | + +### Authority + +| Page | Main-content links | Audit | +|---|---|---| +| `/authority` | MD, `/guides/protect-rest-effect` twice, `/start/delegate-agent`, `/operations`, `/authority/lifecycle`, `/authority/approval-bound-plans`, `/authority/receipts-and-disclosure` | Core verbs leave the section | +| `/authority/lifecycle` | MD, `/get-started/agent`, `/authority` | No topic nav; no code | +| `/authority/approval-bound-plans` | MD, `/get-started/cross-company`, `/authority` | No topic nav; no code | +| `/authority/receipts-and-disclosure` | MD, `/get-started/verify`, `/assurance` | No topic nav; no code | + +### Agents and MCP + +| Page | Main-content links | Audit | +|---|---|---| +| `/agents` | MD, `/start/delegate-agent` twice, `/guides/protect-rest-effect`, `/start/verify-receipt`, `/integrations`, `/identity-trust`, `/operations` | Every card leaves the section; MCP card is misleading | +| `/agents/how-auths-works` | MD only | Orphan; 64 words; no code | +| `/agents/delegate-one-tool` | MD, `/developers` | Orphan; 43 words; no code; scenario link loses context | +| `/agents/approved-plan` | MD, `/developers` | Orphan; 50 words; no code; scenario link loses context | +| `/agents/multi-agent` | MD only | Orphan; 44 words; no code | +| `/agents/mcp-client` | MD only | Orphan; 45 words; no code | +| `/agents/protect-mcp-server` | MD only | Orphan; 46 words; no code | +| `/agents/skills` | MD only | Orphan; 52 words; no code | + +### Integrations + +| Page | Main-content links | Audit | +|---|---|---| +| `/integrations` | `/integrations/index.md` only | No guide links despite six child pages | +| `/integrations/capabilities` | MD only | Orphan; 48 words; no code | +| `/integrations/cloud` | MD only | Orphan; 48 words; no code | +| `/integrations/identity-trust` | MD only | Orphan; 54 words; no code | +| `/integrations/policy` | MD only | Orphan; 49 words; no code | +| `/integrations/profile-kit` | MD only | Orphan; 43 words; no code | +| `/integrations/transport` | MD only | Orphan; 52 words; no code | + +### Production operations + +| Page | Main-content links | Audit | +|---|---|---| +| `/operations` | MD, `/reference/runtime-api` twice, `/architecture`, `/start/verify-receipt`, `/operations/execution-lifecycle`, `/assurance`, `/developers` | Only one card descends into Operations | +| `/operations/evaluate-locally` | MD only | Orphan; 49 words; no commands | +| `/operations/deploy-runtime` | MD only | Orphan; 45 words; no commands | +| `/operations/durable-state` | MD only | Orphan; 48 words; no commands | +| `/operations/custody` | MD only | Orphan; 50 words; no commands | +| `/operations/trust-and-profiles` | MD only | Orphan; 45 words; no commands | +| `/operations/provider-gateways` | MD only | Orphan; 46 words; no commands | +| `/operations/observability` | MD only | Orphan; 47 words; no commands | +| `/operations/backup-and-restore` | MD only | Orphan; 48 words; no commands | +| `/operations/recovery-and-reconciliation` | MD, `/developers` | Orphan; 42 words; scenario link loses context | +| `/operations/upgrade-and-rollback` | MD only | Orphan; 41 words; no commands | +| `/operations/receipt-retention` | MD only | Orphan; 45 words; no procedure | +| `/operations/execution-lifecycle` | MD, `/get-started/runtime`, `/operations` | No topic nav; conceptual only | +| `/operations/incident-response` | MD only | Orphan; structured summaries but no executable runbook flow | + +### Developers and reference + +| Page | Main-content links | Audit | +|---|---|---| +| `/developers` | MD, `/reference/sdk` twice, `/reference/runtime-api`, `/guides/protect-rest-effect`, `/integrations`, `/agents`, `/assurance` | Every card leaves the section | +| `/developers/sdks` | MD only | Orphan; 71 words; no code | +| `/developers/runtime-api` | MD only | Orphan; 62 words; no request example | +| `/developers/cli` | MD only | Orphan; 61 words; no commands | +| `/developers/testing` | MD, `/developers` | Thin; tested-scenario link loses context | +| `/developers/errors` | MD only | Orphan; thin; no per-error pages | +| `/developers/versioning` | MD only | Orphan; thin | +| `/reference` | MD, `/reference/sdk` twice, `/reference/runtime-api`, `/developers`, `/concepts`, `/architecture/trust-boundaries`, `/assurance` | No reference-local nav | +| `/reference/sdk` | six section Markdown links | Strongest page: topic nav, synchronized code, but no onward journey | +| `/reference/runtime-api` | `/reference/sdk`, page MD, five section MD links | Strong page; reference-local nav; no broader developer journey | +| `/reference/cli` | `/reference/cli.md` | Orphan, 21 words, zero commands; Markdown target is missing | +| `/reference/profiles` | MD only | Orphan; 36 words | +| `/reference/errors` | MD only | Orphan; 42 words | +| `/reference/schemas` | MD only | Orphan; 38 words | +| `/reference/evidence` | MD only | Orphan; 37 words | + +### Quickstarts + +Each quickstart renders five code blocks and links to its own Markdown, exact +JSON download, `/developers/testing`, and `/operations`. The source and failure +shape are substantially better than the generic pages, but all seven are +orphans and none has topic navigation. + +| Page | Exact links | Audit | +|---|---|---| +| `/quickstarts/local-rest-effect` | MD, `/downloads/quickstarts/local-rest-effect.json`, `/developers/testing`, `/operations` | Orphan; should live in Get started hierarchy | +| `/quickstarts/runtime-effect` | MD, `/downloads/quickstarts/runtime-effect.json`, `/developers/testing`, `/operations` | Orphan; should live in Get started hierarchy | +| `/quickstarts/agent-delegation` | MD, `/downloads/quickstarts/agent-delegation.json`, `/developers/testing`, `/operations` | Orphan; should be curated by Get started and Agents | +| `/quickstarts/approved-plan` | MD, `/downloads/quickstarts/approved-plan.json`, `/developers/testing`, `/operations` | Orphan; should be curated by Get started and Authority/Agents | +| `/quickstarts/offline-verification` | MD, `/downloads/quickstarts/offline-verification.json`, `/developers/testing`, `/operations` | Orphan; should be curated by Get started and Identity/Authority | +| `/quickstarts/recovery` | MD, `/downloads/quickstarts/recovery.json`, `/developers/testing`, `/operations` | Orphan; should be curated by Get started and Operations | +| `/quickstarts/identity-swap` | MD, `/downloads/quickstarts/identity-swap.json`, `/developers/testing`, `/operations` | Orphan; should be curated by Get started and Identity | + +### Assurance + +| Page | Main-content links | Audit | +|---|---|---| +| `/assurance` | MD, `/architecture/trust-boundaries`, `/architecture`, `/start/verify-receipt`, `/reference`, `/operations`, `/integrations`, `/developers` | No claim page is linked; every card leaves Assurance | +| `/assurance/semantics` | MD only | Orphan; thin | +| `/assurance/authority` | MD only | Orphan; thin | +| `/assurance/execution` | MD only | Orphan; thin | +| `/assurance/disclosure` | MD only | Orphan; thin | +| `/assurance/supply-chain` | MD only | Orphan; thin | +| `/assurance/limitations` | MD only | Orphan; thin | + +## Root causes + +1. **A page registry is being mistaken for information architecture.** It can + prove unique IDs and paths but not that a reader remains oriented. +2. **Landing cards are curated before their destination journeys exist.** A + plausible label is linked to the nearest vaguely related page. +3. **Generic rendering rewards one-paragraph pages.** A valid content record + becomes a published page without meeting a job-specific content contract. +4. **Tested scenarios are linked indirectly.** Generic “Open the tested + scenario” links often go to `/developers`, not to the scenario that produced + the claim. +5. **Route namespaces do not express ownership.** `/start`, `/guides`, + `/quickstarts`, `/adopt`, `/integrations`, and `/reference` compete with the + six primary sections. +6. **Link checks prove existence, not meaning.** There are zero broken HTML + routes and still many broken reader promises. +7. **Left navigation is treated as a special reference feature.** It must be a + universal topic shell for every non-landing content page. + +## Stop conditions + +Do not resume additive editorial expansion until: + +- the proposed hierarchy is approved as the canonical route graph; +- every page has exactly one primary section owner; +- every primary-section landing links first to its own index and child pages; +- every non-landing page renders its owning section's left navigation; +- legacy routes are removed or replaced cleanly (the product is prelaunch); +- guide, quickstart, reference, concept, and runbook page types have distinct + minimum content contracts; and +- qualification detects orphan pages, misleading card intent, missing code, + missing procedures, and missing Markdown. + diff --git a/docs/specs/0040/content/STRIPE_CONTENT_RESEARCH.md b/docs/specs/0040/content/STRIPE_CONTENT_RESEARCH.md new file mode 100644 index 00000000..ba2fbe5b --- /dev/null +++ b/docs/specs/0040/content/STRIPE_CONTENT_RESEARCH.md @@ -0,0 +1,568 @@ +# Stripe Documentation Content Research + +Status: active research notebook +Research date: 2026-08-14 +Target: at least 40 distinct live Stripe documentation pages + +## Purpose + +This notebook studies how Stripe turns a large technical product into a +progressively disclosed documentation system. It records observable content +and navigation patterns that Auths can adapt without copying Stripe's prose, +visual identity, or product taxonomy. + +The research asks: + +1. What job does each topic landing page perform before technical detail? +2. How does global navigation hand off to contextual left navigation? +3. How do overview, tour, quickstart, concept, design, and reference pages + differ? +4. How does a reader move from choosing an outcome to implementing it? +5. Which patterns suit Auths, and which are specific to Stripe's product? + +## Method + +- Inspect at least 40 distinct pages in the live Stripe documentation. +- Begin from global topic destinations, then follow contextual links into + representative journeys. +- Record observations in batches immediately after inspection. +- Cite the exact Stripe page beside every page-specific observation. +- Separate observed behavior from recommendations for Auths. +- Finish with an evidence ledger and derive executable Auths content epics in + sibling files. + +## Page ledger + +| # | Area | Page | Page role | Inspected | +|---:|---|---|---|---| +| 1 | Global | [Get started](https://docs.stripe.com/get-started) | Topic landing | Yes | +| 2 | Global | [Payments](https://docs.stripe.com/payments) | Topic landing | Yes | +| 3 | Global | [Revenue](https://docs.stripe.com/revenue) | Topic landing | Yes | +| 4 | Global | [Developer resources](https://docs.stripe.com/development) | Topic landing | Yes | +| 5 | Developer | [SDKs](https://docs.stripe.com/sdks) | Catalog landing | Yes | +| 6 | Developer | [APIs](https://docs.stripe.com/apis) | Concept catalog landing | Yes | +| 7 | Agents | [Agents and AI](https://docs.stripe.com/agents) | Audience/use-case landing | Yes | +| 8 | Get started | [Quickstarts](https://docs.stripe.com/quickstarts) | Task catalog landing | Yes | +| 9 | Migration | [Data migrations overview](https://docs.stripe.com/get-started/data-migrations/overview) | Process overview | Yes | +| 10 | Migration | [Import payment method data](https://docs.stripe.com/get-started/data-migrations/payment-method-imports) | Deep operational guide | Yes | +| 11 | Payments | [Tour of the API](https://docs.stripe.com/payments-api/tour) | Conceptual API tour | Yes | +| 12 | Payments | [Checkout Sessions API](https://docs.stripe.com/payments/checkout-sessions) | Recommended abstraction overview | Yes | +| 13 | Agents | [How agents work with Stripe](https://docs.stripe.com/agents/how-it-works) | Architecture and composition guide | Yes | +| 14 | Get started | [Stripe accounts](https://docs.stripe.com/get-started/account) | Prerequisite catalog | Yes | +| 15 | Get started | [Development environment](https://docs.stripe.com/get-started/development-environment) | Environment quickstart | Yes | +| 16 | Get started | [API keys](https://docs.stripe.com/keys) | Security concept and operations guide | Yes | +| 17 | Get started | [Testing](https://docs.stripe.com/testing) | Scenario catalog | Yes | +| 18 | Get started | [No-code integration](https://docs.stripe.com/no-code/get-started) | Audience-specific solution guide | Yes | +| 19 | Get started | [Startup payments](https://docs.stripe.com/get-started/use-cases/startup) | Outcome recipe | Yes | +| 20 | Get started | [SaaS subscriptions](https://docs.stripe.com/get-started/use-cases/saas-subscriptions) | Outcome recipe | Yes | +| 21 | Payments | [Design a payments integration](https://docs.stripe.com/payments/use-cases/get-started) | Product chooser | Yes | +| 22 | Payments | [Build a payments page](https://docs.stripe.com/payments/checkout) | Capability landing | Yes | +| 23 | Payments | [Stripe-hosted Checkout](https://docs.stripe.com/checkout/quickstart) | Interactive quickstart | Yes | +| 24 | Payments | [Embedded Checkout](https://docs.stripe.com/checkout/embedded/quickstart) | Interactive quickstart | Yes | +| 25 | Payments | [Checkout Sessions quickstart](https://docs.stripe.com/payments/quickstart) | Interactive quickstart | Yes | +| 26 | Payments | [Web Elements](https://docs.stripe.com/payments/elements) | Component landing | Yes | +| 27 | Payments | [Supported payment methods](https://docs.stripe.com/payments/payment-methods/overview) | Compatibility catalog | Yes | +| 28 | Payments | [Payment Intents API](https://docs.stripe.com/payments/payment-intents) | Lifecycle concept guide | Yes | +| 29 | Payments | [Setup Intents API](https://docs.stripe.com/payments/setup-intents) | Lifecycle concept guide | Yes | +| 30 | Developer | [Webhook quickstart](https://docs.stripe.com/webhooks/quickstart) | Interactive quickstart | Yes | +| 31 | Revenue | [Billing](https://docs.stripe.com/billing) | Product landing | Yes | +| 32 | Revenue | [Billing quickstart](https://docs.stripe.com/billing/quickstart) | Interactive quickstart | Yes | +| 33 | Revenue | [Design a subscriptions integration](https://docs.stripe.com/billing/subscriptions/design-an-integration) | Design decision guide | Yes | +| 34 | Revenue | [How subscriptions work](https://docs.stripe.com/billing/subscriptions/overview) | Lifecycle concept guide | Yes | +| 35 | Revenue | [Recurring pricing models](https://docs.stripe.com/products-prices/pricing-models) | Domain model catalog | Yes | +| 36 | Revenue | [Invoicing](https://docs.stripe.com/invoicing) | Product landing | Yes | +| 37 | Revenue | [Set up Stripe Tax](https://docs.stripe.com/tax/set-up) | Configuration procedure | Yes | +| 38 | Revenue | [Revenue Recognition](https://docs.stripe.com/revenue-recognition/get-started) | Product onboarding guide | Yes | +| 39 | Revenue | [How Sigma works](https://docs.stripe.com/data/how-sigma-works) | Boundary-first capability guide | Yes | +| 40 | Revenue | [How Data Pipeline works](https://docs.stripe.com/data/access-data-in-warehouse) | Integration capability guide | Yes | +| 41 | Revenue | [Subscriptions](https://docs.stripe.com/subscriptions) | Subdomain landing | Yes | +| 42 | Agents | [Model Context Protocol](https://docs.stripe.com/mcp) | Tool integration guide | Yes | +| 43 | Agents | [Agent skills](https://docs.stripe.com/skills) | Installation and catalog guide | Yes | +| 44 | Developer | [Stripe CLI](https://docs.stripe.com/cli) | Generated command reference | Yes | +| 45 | Developer | [Server-side SDKs](https://docs.stripe.com/sdks/server-side) | Cross-language SDK guide | Yes | +| 46 | Developer | [SDK versioning](https://docs.stripe.com/sdks/versioning) | Compatibility policy | Yes | +| 47 | Developer | [Automated testing](https://docs.stripe.com/automated-testing) | Testing strategy guide | Yes | +| 48 | Developer | [Error handling](https://docs.stripe.com/error-handling) | Cross-language failure guide | Yes | +| 49 | Assurance | [Security at Stripe](https://docs.stripe.com/security) | Assurance landing | Yes | +| 50 | Developer | [Stripe-Context header](https://docs.stripe.com/context) | Request-scope concept guide | Yes | + +## Batch notes + +### Batch 1 — Global landings, catalogs, and depth transitions + +Pages 1–10 establish the outer information architecture and show how Stripe +hands a reader from a broad product promise into increasingly specific work. + +#### Observations + +1. A global topic destination is a curated decision surface, not a table of + contents. The Get Started page first offers account setup and development + prerequisites, then outcome-shaped common use cases, migration, testing, + and help. Each card combines an action title with a one-sentence promise. + [Evidence: Get started](https://docs.stripe.com/get-started) + +2. Product landings use the same structural grammar but change their grouping + logic. Payments groups the landscape by payment outcome, payment method, + adjacent financial job, platform model, and deeper technical concepts; + Revenue groups by the business lifecycle domains Billing, Tax, Reporting, + and Data. [Evidence: Payments](https://docs.stripe.com/payments), + [Revenue](https://docs.stripe.com/revenue) + +3. The global navigation remains a small collection of audience-sized domains. + The contextual left navigation becomes the complete local map. The landing + page therefore explains and recommends; the sidebar enumerates. Stripe does + not force the global header to carry every product or subtopic. + [Evidence: Get started](https://docs.stripe.com/get-started), + [Developer resources](https://docs.stripe.com/development) + +4. The Developer Resources landing is an ecosystem map rather than an SDK + page. It distinguishes CLI, SDKs, APIs, agents, MCP, testing, versioning, + operational tools, security, extensions, and community. This prevents + developers from assuming the client library is the whole platform. + [Evidence: Developer resources](https://docs.stripe.com/development) + +5. Catalog pages carry real explanatory value before listing destinations. + The SDK page explains where server, web, and mobile libraries fit and + exposes current versions; the API page explains the shared request model, + then groups authentication, response shaping, pagination, testing, and + errors. [Evidence: SDKs](https://docs.stripe.com/sdks), + [APIs](https://docs.stripe.com/apis) + +6. Quickstarts are treated as a content type with an explicit promise: + end-to-end examples, framework/language choices, stepwise implementation, + and a runnable or downloadable path. The Quickstarts landing categorizes + them by outcome instead of presenting an undifferentiated tutorial list. + [Evidence: Quickstarts](https://docs.stripe.com/quickstarts) + +7. The Agents landing mixes a literal copyable starting prompt with a map of + agent tooling, commerce use cases, billing, and open protocols. That page + serves both someone using an agent to build and someone building an agentic + product; it names the distinction without creating two disconnected docs + sites. [Evidence: Agents and AI](https://docs.stripe.com/agents) + +8. Deep operational content begins with an outcome contract. The migration + overview tells readers what they will understand, then divides the work into + build, learn, plan, coordinate, migrate, and update phases. It connects each + phase to the next relevant technical or organizational surface. + [Evidence: Data migrations overview](https://docs.stripe.com/get-started/data-migrations/overview) + +9. The payment-method import guide is allowed to become dense because the + reader has already crossed an overview boundary. It opens with method tabs, + then covers defaults, limitations, regulatory evidence, file requirements, + field-level details, and output review. This depth belongs below—not on—the + migration landing page. + [Evidence: Import payment method data](https://docs.stripe.com/get-started/data-migrations/payment-method-imports) + +#### Implications for Auths + +- Keep global navigation bounded to durable user domains; give each one a real + landing page before exposing its detailed tree. +- Make landing pages recommend routes by outcome and reader job, not merely + repeat sidebar links. +- Define distinct templates for topic landing, catalog landing, quickstart, + process overview, and deep operational guide. +- Give Auths an ecosystem/developer landing that distinguishes SDKs, Runtime + API, CLI, agent/MCP tooling, integrations, testing, and assurance. +- Let operational and cryptographic depth live behind overview pages that tell + readers why and when they need it. + +### Batch 2 — Tours, prerequisites, testing, and outcome recipes + +Pages 11–20 show that progressive disclosure is not merely shallow-to-deep. +Stripe uses different intermediate page types to answer different questions +before the reader reaches reference material. + +#### Observations + +1. An API tour explains the object system and lifecycle before teaching + individual calls. It explicitly promises to help readers move beyond copied + tutorial code by showing common patterns and how objects fit together. + [Evidence: Tour of the API](https://docs.stripe.com/payments-api/tour) + +2. Stripe recommends a default abstraction and explains why. The Checkout + Sessions overview describes the capabilities it bundles, identifies the UI + forms it supports, and positions it as the default for most integrations + before discussing its lifecycle. This reduces premature choice overload. + [Evidence: Checkout Sessions API](https://docs.stripe.com/payments/checkout-sessions) + +3. The agent architecture page begins with independent components, shows how + each connects to the product, and then documents common combinations. It + does not imply that adopting agent developer tooling also requires billing + or agentic commerce. + [Evidence: How agents work with Stripe](https://docs.stripe.com/agents/how-it-works) + +4. Prerequisite pages remain scoped. The account page separates immediate + sandbox availability from live-account activation and then routes into + account-management tasks rather than mixing them into every quickstart. + [Evidence: Stripe accounts](https://docs.stripe.com/get-started/account) + +5. The development-environment guide states what the reader will learn, offers + an explicit non-developer exit, introduces CLI and SDK roles, and then moves + through installation to a first request. Audience branching happens near + the top instead of after irrelevant setup. + [Evidence: Development environment](https://docs.stripe.com/get-started/development-environment) + +6. Security documentation combines conceptual taxonomy with operational + handling. The API-key page explains key types, sandbox/live distinctions, + protection, rotation, request logs, and access policy from one durable + security landing. + [Evidence: API keys](https://docs.stripe.com/keys) + +7. Testing is organized as a scenario catalog, not a generic admonition to + test. Readers can deliberately simulate success, brands, countries, + declines, fraud, invalid data, disputes, refunds, authentication, webhooks, + and other outcome classes. + [Evidence: Testing](https://docs.stripe.com/testing) + +8. No-code is a first-class audience path with its own decision guide. The + page recommends components by business job—online payment, subscriber + retention, invoicing, in-person payment, tips—without exposing API detail. + [Evidence: No-code integration](https://docs.stripe.com/no-code/get-started) + +9. Use-case pages are linear outcome recipes. The startup guide sequences + account, payment link, sharing, go-live, and next steps; the SaaS guide adds + product/price modeling, subscriptions, recommended configuration, + monitoring, and go-live. Both choose an opinionated path for a named reader. + [Evidence: Startup payments](https://docs.stripe.com/get-started/use-cases/startup), + [SaaS subscriptions](https://docs.stripe.com/get-started/use-cases/saas-subscriptions) + +#### Implications for Auths + +- Add an Auths semantic tour that explains how actor, action, authority, + outcome, and receipt fit together before any symbol-level reference. +- Publish a clearly recommended default integration for ordinary applications, + then show where lower-level profiles and ports are appropriate. +- Explain that identity, policy, transport, custody, and provider integrations + compose independently; never present the full stack as mandatory. +- Give each onboarding page an early exit to the correct audience path: local + library, hosted runtime, agent/MCP workflow, integration author, or operator. +- Build testing documentation as adversarial scenario recipes: success, + denial, expiry, replay, mutation, revocation, indeterminate, recoverable, and + provider-unknown. +- Create named outcome recipes rather than one universal quickstart. + +### Batch 3 — Product choice, interactive quickstarts, and lifecycle concepts + +Pages 21–30 show how Stripe helps a developer choose an integration, complete +one working path, and then understand the lower-level lifecycle beneath it. + +#### Observations + +1. A product chooser starts from business and UX constraints, not product + names. The payments design guide contrasts no-code, hosted, embedded, and + custom paths and lets the reader discover which surface fits before opening + implementation detail. + [Evidence: Design a payments integration](https://docs.stripe.com/payments/use-cases/get-started) + +2. A capability landing sits between chooser and quickstart. The Checkout page + explains the shared API, visually distinguishes hosted, embedded, and + element-based interfaces, then routes into customization, collection + timing, and business management. + [Evidence: Build a payments page](https://docs.stripe.com/payments/checkout) + +3. Interactive quickstarts are a distinct application surface. They offer + frontend and backend selectors, synchronized examples, numbered progress, + highlighted implementation lines, complete downloadable projects, a text + alternative, and an explicit no-code exit. + [Evidence: Stripe-hosted Checkout](https://docs.stripe.com/checkout/quickstart), + [Embedded Checkout](https://docs.stripe.com/checkout/embedded/quickstart), + [Checkout Sessions quickstart](https://docs.stripe.com/payments/quickstart) + +4. Closely related quickstarts reuse one interaction grammar while changing + only the integration boundary. Hosted Checkout teaches redirect; Embedded + Checkout teaches an embedded form; the Checkout Sessions quickstart teaches + a custom page backed by managed session semantics. Familiar scaffolding + makes the architectural difference easier to see. + [Evidence: Stripe-hosted Checkout](https://docs.stripe.com/checkout/quickstart), + [Embedded Checkout](https://docs.stripe.com/checkout/embedded/quickstart), + [Checkout Sessions quickstart](https://docs.stripe.com/payments/quickstart) + +5. Component landings state the security boundary and product value before + setup. The Elements page explains that sensitive details are tokenized + without touching the application server, then lists global methods, + compliance, saved methods, and compatible APIs. + [Evidence: Web Elements](https://docs.stripe.com/payments/elements) + +6. Compatibility catalogs explain why variation matters before enumerating it. + The payment-method page introduces regional preference and per-method + currency, country, product, and API constraints before its category tree. + [Evidence: Supported payment methods](https://docs.stripe.com/payments/payment-methods/overview) + +7. Lifecycle concept pages justify lower-level objects with the stateful + problem they solve. Payment Intents explains changing payment state, + authentication, idempotency, and post-payment work; Setup Intents explains + preparing and authenticating a payment method now for future use without a + charge. + [Evidence: Payment Intents API](https://docs.stripe.com/payments/payment-intents), + [Setup Intents API](https://docs.stripe.com/payments/setup-intents) + +8. The webhook quickstart attaches asynchronous infrastructure to a concrete + post-effect job—receipts, fulfillment, database updates—rather than teaching + event delivery in isolation. It uses the same language-selectable, + downloadable quickstart grammar as product integrations. + [Evidence: Webhook quickstart](https://docs.stripe.com/webhooks/quickstart) + +#### Implications for Auths + +- Add an integration chooser that begins with deployment and trust constraints: + local verification, hosted runtime, agent delegation, cross-company action, + or custom profile/adapter. +- Insert capability landings between the chooser and technical guides—for + example “Protect an application effect,” “Delegate to an agent,” “Run an + approval-bound plan,” and “Verify portable evidence.” +- Standardize a real interactive quickstart shell across Rust, TypeScript, and + Python: selected language, numbered steps, tested source, expected outcome, + downloadable project, text alternative, and explicit next steps. +- Pair high-level defaults with lifecycle tours for authority, execution, + recovery, and receipt disclosure. +- Make every adapter/catalog page state its security boundary and compatibility + dimensions before listing implementations. + +### Batch 4 — Product landings, design decisions, and operational boundaries + +Pages 31–40 show how Stripe documents a broad business domain after the reader +has entered it from a global Revenue landing. + +#### Observations + +1. A product landing can serve operators and developers together without + collapsing their paths. Billing presents no-code options, subscription + onboarding, usage billing, invoicing, quotes, a sample project, and a feature + catalog as separate choices under one product promise. + [Evidence: Billing](https://docs.stripe.com/billing) + +2. A sophisticated quickstart can expose an explicit integration-path switch + in addition to frontend and backend language choices. The Billing quickstart + lets readers select customer/account modeling while retaining the same + guided, downloadable sample experience. + [Evidence: Billing quickstart](https://docs.stripe.com/billing/quickstart) + +3. Design guides identify the small number of decisions that materially shape + an implementation. The subscriptions design page asks how to charge, how + customers check out, and when they pay, then routes the selected combination + into build guides. + [Evidence: Design a subscriptions integration](https://docs.stripe.com/billing/subscriptions/design-an-integration) + +4. Lifecycle guides explain the state machine independently from setup. The + subscriptions overview describes creation through cancellation, separates + subscription status from payment status, and connects phases to object state. + [Evidence: How subscriptions work](https://docs.stripe.com/billing/subscriptions/overview) + +5. Domain-model catalogs map business language to product objects. The pricing + guide explains products, prices, currency, and service period, then compares + flat-rate, per-seat, tiered, and usage patterns. + [Evidence: Recurring pricing models](https://docs.stripe.com/products-prices/pricing-models) + +6. Product landings consistently lead with multiple operational modes. The + Invoicing page distinguishes Dashboard/no-code workflows, accounts + receivable automation, API integration, and adjacent product comparison + before deep configuration. + [Evidence: Invoicing](https://docs.stripe.com/invoicing) + +7. Configuration procedures present an ordered operational checklist and name + alternative control surfaces. Stripe Tax walks through address, tax code, + inclusive pricing, registrations, integration/API enablement, filing, and + disabling collection; it also separates platform-specific responsibility. + [Evidence: Set up Stripe Tax](https://docs.stripe.com/tax/set-up) + +8. Product onboarding includes evaluation before production. Revenue + Recognition introduces imports, rules, reports, and transaction-model tests, + and makes sandbox/trial use part of the documented path. + [Evidence: Revenue Recognition](https://docs.stripe.com/revenue-recognition/get-started) + +9. Capability guides lead with hard boundaries when misuse would be costly. + Sigma states that queries are read-only before describing reporting and + metrics. Data Pipeline states its one-way export purpose, supported + destinations, schemas, multi-account model, sandbox behavior, and shutdown. + [Evidence: How Sigma works](https://docs.stripe.com/data/how-sigma-works), + [How Data Pipeline works](https://docs.stripe.com/data/access-data-in-warehouse) + +#### Implications for Auths + +- Give each major Auths domain a landing that serves builders, integrators, and + operators with separate recommended paths. +- Build design-decision guides around the few choices that actually alter the + architecture: local versus service runtime, identity/trust source, approval + policy, custody, state store, transport, and provider gateway. +- Publish lifecycle/state-machine pages separately from quickstarts for grants, + plans, executions, recovery references, and receipts. +- Translate application intent into Auths domain objects with comparison tables + and worked examples. +- Put hard boundaries first: offline versus effectful, inert versus executable, + public identity versus secret custody, transport versus authorization, and + completed versus provider-unknown. +- Include sandbox/evaluation and safe shutdown paths in every operational + integration guide. + +### Batch 5 — SDKs, CLI, agents, failures, and assurance + +Pages 41–50 cover the cross-cutting developer surfaces most analogous to Auths. + +#### Observations + +1. A subdomain landing remains useful even when a parent product landing + exists. Subscriptions narrows Billing into sample integration, conceptual + overview, design choices, no-code options, webhooks, integrations, and + feature expansion. The reader does not need to rediscover this path inside + the broader Billing page. + [Evidence: Subscriptions](https://docs.stripe.com/subscriptions) + +2. The MCP guide distinguishes using Stripe's MCP server from building an MCP + application that accepts payments. It then gives client-specific connection + instructions, enumerates tools, and separately covers connected-account and + Treasury contexts. + [Evidence: Model Context Protocol](https://docs.stripe.com/mcp) + +3. Agent skills documentation recommends maintained, automatically updated + plugins first and places manual installation behind a warning. It follows + installation with a skills index rather than treating setup as the entire + product. + [Evidence: Agent skills](https://docs.stripe.com/skills) + +4. CLI reference uses a purpose-built information architecture rather than the + prose-page template. Its left navigation is grouped by getting started, + documentation, webhooks, resources/HTTP, projects, tools, and commands; the + content begins with purpose and installation, then exposes exhaustive + commands, subcommands, flags, examples, credential behavior, and sandbox + lifecycle. + [Evidence: Stripe CLI](https://docs.stripe.com/cli) + +5. A cross-language SDK guide synchronizes language selection across setup and + core tasks. It covers installation, initialization, requests, response + access, expansion, request IDs, per-request options, errors, escape hatches, + source code, client construction, and preview channels—not only a package + install command. + [Evidence: Server-side SDKs](https://docs.stripe.com/sdks/server-side) + +6. Compatibility policy is a first-class page. Stripe explains API cadence, + SDK semantic versions, breaking-change timing, SDK support windows, runtime + support, and preview channels in one place. + [Evidence: SDK versioning](https://docs.stripe.com/sdks/versioning) + +7. Automated-testing guidance states constraints before recommendations. + Stripe explains why security controls and rate limits make direct automation + unsuitable for some interfaces, then recommends simulated client and server + outputs to test application behavior and failure recovery. + [Evidence: Automated testing](https://docs.stripe.com/automated-testing) + +8. Error documentation is cross-language and action-oriented. It first teaches + the common error envelope, exception handling, webhook monitoring, and stored + failure information, then separates declines, invalid requests, connection, + API, authentication, idempotency, permission, rate-limit, and signature + failures. + [Evidence: Error handling](https://docs.stripe.com/error-handling) + +9. Assurance has a dedicated narrative surface. Stripe separates standards and + regulatory compliance, product security, infrastructure safeguards, and + ongoing posture maintenance instead of mixing every assurance claim into + product quickstarts. + [Evidence: Security at Stripe](https://docs.stripe.com/security) + +10. Request-context documentation uses a concrete organization hierarchy to + teach scope. It explains the default scope, the explicit override, which + related accounts are reachable, and how the requested context relates to + the key's authority. + [Evidence: Stripe-Context header](https://docs.stripe.com/context) + +#### Implications for Auths + +- Create subdomain landings for authority, agents, approvals, execution, + recovery, receipts, integrations, and assurance beneath the bounded global + destinations. +- Separate “use Auths with an agent/MCP client” from “build a protected MCP + server or agent product.” +- Treat maintained agent plugins/skills as an onboarding channel with explicit + versioning and security boundaries, not as copied prompt snippets. +- Give the CLI a generated command-reference template while retaining a short + outcome-oriented CLI landing page. +- Expand the SDK guide into the full cross-language journey: install, compose, + create, delegate, execute, resume, verify, inspect outcomes, handle errors, + test, and find source. +- Publish explicit support/version policy before launch. +- Build a failure-handling hub around Auths' closed outcomes and stable error + identities, with language-specific handling examples. +- Keep assurance evidence in its own navigable domain, and link precise claims + from product pages rather than duplicating them. + +## Synthesis + +### The reusable content grammar + +Stripe's pages repeatedly form this progression: + +```text +global topic + -> curated landing + -> chooser or design guide + -> opinionated quickstart + -> lifecycle/concept guide + -> generated reference + -> operations, testing, and assurance +``` + +The progression is not a mandatory funnel. A knowledgeable reader can enter at +reference or operations, while a new reader receives progressively more detail. +The key is that each page has one recognizable job. + +### Proposed Auths global information architecture + +```text ++--------------------------------------------------------------------------------+ +| Auths Docs Search APIs & SDKs GitHub | +| Get started | Identity & trust | Authority | Agents | Operations | Developers | ++--------------------------------------------------------------------------------+ +| Contextual left navigation | Recommended landing or focused content | Outline | ++--------------------------------------------------------------------------------+ +``` + +Decisions: + +- `Get started` owns prerequisites, the integration chooser, quickstarts, + evaluation, adoption, and migration. +- `Identity & trust` explains identity agnosticism, verification methods, + evidence, resolvers, trust roots, and authentication composition. +- `Authority` owns actions, grants, attenuation, delegation, approvals, plans, + execution, recovery, outcomes, receipts, and disclosure. +- `Agents` owns agent delegation, MCP client/server journeys, approval-bound + plans, skills/plugins, and multi-agent patterns. +- `Operations` owns production runtime deployment, state, custody, + observability, recovery, incident response, and runbooks. +- `Developers` owns local tooling, CLI, testing, errors, integrations, profile + development, versioning, changelog, contribution, and assurance entry points. +- `APIs & SDKs` is a visually distinct utility destination for generated Rust, + TypeScript, Python, Runtime API, CLI, schema, and stable-error references. +- `Assurance` remains a first-class landing with strong cross-links from + Authority, Operations, and Developers; it does not consume a primary tab. + +### Page types Auths must support + +| Page type | Reader question | Required shape | +|---|---|---| +| Topic landing | “Where do I begin in this domain?” | Promise, recommended path, grouped cards, audience exits | +| Product/capability landing | “What does this surface do?” | Boundary, value, modes, common jobs, next steps | +| Chooser | “Which integration fits?” | Decision dimensions, recommendations, comparison, route | +| Design guide | “Which decisions alter my architecture?” | Small decision set, tradeoffs, resulting path | +| Quickstart | “Can I make one thing work?” | Tested project, steps, languages, outcome, failure, download | +| Tour | “How does the model fit together?” | Nouns, lifecycle, diagrams, common combinations | +| Concept/lifecycle | “Why does this primitive exist?” | Problem, state model, invariants, failure paths, links | +| Operations procedure | “How do I run this safely?” | Preconditions, commands, checks, rollback, escalation | +| Catalog | “What is supported?” | Compatibility dimensions, generated inventory, constraints | +| Reference | “What is the exact contract?” | Generated facts, sticky examples, stable identities, errors | +| Assurance | “Why should I trust this claim?” | Claim, evidence, limitation, version, reproduction | + +### Content laws + +1. Every global topic has a curated landing page. +2. Landing pages recommend; sidebars enumerate. +3. Every quickstart produces one observable success and at least one safe + failure. +4. Every effectful guide names the trust, custody, state, and provider boundary. +5. Every reference fact comes from a release artifact, never copied prose. +6. Every language switch preserves semantics and changes only idiomatic syntax. +7. Every lifecycle explains denied, indeterminate, recoverable, and unknown + outcomes where applicable. +8. Every assurance claim links to versioned evidence and states limitations. +9. Every page has canonical Markdown and bounded section projections. +10. Every deep page links back to its overview and forward to the next likely + task. + diff --git a/docs/specs/0040/content/content_epic_1.md b/docs/specs/0040/content/content_epic_1.md new file mode 100644 index 00000000..31d22405 --- /dev/null +++ b/docs/specs/0040/content/content_epic_1.md @@ -0,0 +1,121 @@ +# Content Epic 1 — Global Information Architecture and Topic Landings + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Status:** Complete in `auths-docs` commit `fff25d1`. + +**Depends on:** [Content Epic 0](./epic_0.md) and Platform Epics P5–P6. + +**Ownership:** This epic owns public taxonomy, route selection, landing-card +curation, and explanatory copy. Platform code owns the typed navigation and +landing models and validates every referenced page identity. + +## Outcome + +Replace the implementation-oriented global navigation with durable reader +domains and give every domain a curated landing page before its detailed tree. + +## Current problem + +The current header exposes `Start`, `SDKs`, `Runtime API`, `Concepts`, +`Architecture`, and `Operations`. This mixes a journey, two reference formats, +two explanatory content types, and one operating domain. It cannot scale without +turning the global bar into a sitemap, and it offers no first-class route for +identity/trust or agent builders. + +Stripe's global topics lead to curated landing pages, while local sidebars carry +the exhaustive domain tree. [Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-1--global-landings-catalogs-and-depth-transitions) + +## Information architecture + +```text +Primary topics +├── Get started +├── Identity & trust +├── Authority +├── Agents +├── Operations +└── Developers + +Utility destinations +├── APIs & SDKs +├── Search +└── GitHub + +Cross-linked domain +└── Assurance +``` + +## Required landing routes + +| Stable page identity | Route | Reader promise | +|---|---|---| +| `auths.page.start/1` | `/get-started` | Choose and complete the right first Auths path | +| `auths.page.identity-trust/1` | `/identity-trust` | Bring identity and trust without adopting a fixed provider or suite | +| `auths.page.authority/1` | `/authority` | Create, narrow, approve, execute, recover, and prove exact authority | +| `auths.page.agents/1` | `/agents` | Give agents bounded authority without granting ambient credentials | +| `auths.page.operations/1` | `/operations` | Run the open runtime safely in production | +| `auths.page.developers/1` | `/developers` | Find SDKs, tools, testing, integrations, and extension contracts | +| `auths.page.reference/1` | `/reference` | Choose SDK, Runtime API, CLI, schema, error, or evidence reference | +| `auths.page.assurance/1` | `/assurance` | Inspect claims, evidence, limitations, and reproduction | + +## Landing-page contract + +Every landing must contain, in order: + +1. one outcome-oriented `h1` and one-sentence promise; +2. one recommended path with a primary action; +3. three to six grouped task cards with descriptions; +4. explicit audience exits where another landing is more appropriate; +5. “understand first” links to tours or design guides; +6. “build now” links to qualified quickstarts; +7. “go deeper” links to operations, reference, or assurance; +8. canonical page Markdown actions; and +9. generated contextual navigation from stable page identities. + +Landing cards must not duplicate the entire sidebar. Cards are editorial and +ordered; the sidebar is exhaustive and generated. + +## Implementation steps + +- [ ] Declare the eight page identities and dependencies in the authored page + manifest accepted by P6. +- [ ] Author the six-topic global navigation configuration and separate + `APIs & SDKs` utility destination. +- [ ] Curate the contextual tree for each topic from verified page identities. +- [ ] Author the eight landing pages from the page contract above. +- [ ] Declare breadcrumb and back-to-landing relationships for every descendant + page. +- [ ] Preserve direct aliases from `/sdk`, `/reference/sdk`, and existing + public routes only where the prelaunch route map explicitly chooses them; + remove accidental duplicate destinations. +- [ ] Review the P6/P10 renderings of the same page graph across HTML, + canonical Markdown, sitemap, search, and navigation. +- [ ] Qualify navigation at wide, medium, and narrow breakpoints. + +## Acceptance criteria + +- Every global topic opens a useful landing, not the first child article. +- No global navigation item names a page format such as “Concepts” or + “Architecture.” +- APIs and SDKs remain reachable in one action from every page. +- A landing never contains more than six groups or more than six cards per + group. +- Collapsing contextual navigation widens the reading surface. +- Keyboard, screen-reader, zoom, reduced-motion, and mobile navigation tests + pass. +- Every landing has a canonical `.md` projection and no hand-authored reference + facts. + +## Validation + +```text +npm run typecheck +npm run lint +npm run test:content +npm run test:navigation +npm run test:a11y +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_10.md b/docs/specs/0040/content/content_epic_10.md new file mode 100644 index 00000000..38ae4d73 --- /dev/null +++ b/docs/specs/0040/content/content_epic_10.md @@ -0,0 +1,44 @@ +# Content Epic 10 — Canonical Information Architecture and Route Ownership + +**Status:** Complete in `auths-docs` commit `d3dc5db`. + +**Depends on:** Content Epic 0 and +[`SITE_CONTENT_AND_LINK_AUDIT.md`](./SITE_CONTENT_AND_LINK_AUDIT.md). + +## Outcome + +Every public page has one primary section owner, one canonical route, one +stable identity, and a declared place in the complete documentation tree. + +## Current problem + +The site has 92 valid routes but no binding topic hierarchy. Legacy namespaces +(`/start`, `/guides`, `/quickstarts`, `/adopt`, and `/integrations`) make +ownership ambiguous. Sixty pages are navigational orphans. + +## Implementation + +- [x] Encode the complete tree in + [`PROPOSED_SITE_HIERARCHY.md`](./PROPOSED_SITE_HIERARCHY.md) as a strict, + parseable navigation contract. +- [x] Give every page `section`, `parent`, `navGroup`, `order`, and canonical + `path` fields. +- [x] Reject missing parents, cycles, duplicate order, cross-section parents, + and pages absent from the tree. +- [x] Move adoption and quickstarts under `/get-started`. +- [x] Move integrations under `/developers/integrations`. +- [x] Replace legacy `/start/*` and `/guides/*` routes with canonical section + pages; prelaunch means no compatibility aliases are required. +- [x] Keep `/reference` and `/assurance` as explicit cross-cutting utilities. +- [x] Produce a migration manifest mapping every old page identity and path to + its retained, replaced, merged, or deleted destination. +- [x] Delete generic pages that cannot name a distinct reader job. + +## Acceptance + +- All public pages occur exactly once in the canonical tree. +- No primary-section landing needs an unrelated namespace to represent its + first layer of content. +- The route graph has no orphan, cycle, missing parent, or ambiguous owner. +- Old paths are absent from source, rendered links, search, sitemap, and + Markdown surfaces. diff --git a/docs/specs/0040/content/content_epic_11.md b/docs/specs/0040/content/content_epic_11.md new file mode 100644 index 00000000..dc3b3eb8 --- /dev/null +++ b/docs/specs/0040/content/content_epic_11.md @@ -0,0 +1,45 @@ +# Content Epic 11 — Topic Shell, Left Navigation, and Page-Type Contracts + +**Status:** Complete in `auths-docs` commit `dacd29b`. + +**Depends on:** Content Epic 10 and Platform Epics P5–P6. + +## Outcome + +Every page preserves the reader's location and every page type must satisfy a +job-specific minimum content contract before it can render publicly. + +## Current problem + +Eighty-three pages lack left navigation. The generic editorial renderer allows +a title and one paragraph to masquerade as a complete guide, reference page, +integration, or runbook. + +## Implementation + +- [x] Build one reusable `TopicShell` with global navigation, collapsible + topic-local left navigation, breadcrumbs, active state, previous/next, and + mobile drawer behavior. +- [x] Render the same topic tree on landings, guides, quickstarts, concepts, + integrations, operations pages, and reference introductions. +- [x] Define closed schemas for `landing`, `concept`, `guide`, `quickstart`, + `integration`, `reference`, and `runbook`. +- [x] Require guides to contain outcome, prerequisites, ordered steps, code or + an explicit no-code rationale, success, fail-closed behavior, and next step. +- [x] Require integrations to contain ownership matrix, data flow, secrets, + state, failure ownership, executable composition, and limitations. +- [x] Require runbooks to contain owner, severity, preconditions, tested + commands, observations, stop conditions, rollback/resume, reconciliation, + retention, and escalation. +- [x] Require reference pages to resolve generated signatures or inventories; + prose alone cannot qualify as reference. +- [x] Label cross-topic cards as **Related topics**, never **Open guide** inside + the primary content sequence. +- [x] Add responsive, keyboard, screen-reader, and nav-collapse tests. + +## Acceptance + +- Every non-landing public page renders the correct owning topic navigation. +- A page cannot build when its type-specific required blocks are missing. +- Mobile and desktop navigation expose identical hierarchy and active state. +- Reference and quickstart layouts retain synchronized floating code behavior. diff --git a/docs/specs/0040/content/content_epic_12.md b/docs/specs/0040/content/content_epic_12.md new file mode 100644 index 00000000..0b0fdddf --- /dev/null +++ b/docs/specs/0040/content/content_epic_12.md @@ -0,0 +1,34 @@ +# Content Epic 12 — Rebuild Get Started as an Executable Journey + +**Depends on:** Content Epics 10–11 and the seven qualified scenarios. + +## Outcome + +A new reader chooses a path, runs a real cross-language example, observes one +success and one fail-closed outcome, and knows where to continue. + +## Implementation + +- [x] Build the Get started tree exactly as declared in + `PROPOSED_SITE_HIERARCHY.md`. +- [x] Move all seven quickstarts beneath `/get-started/quickstarts` and render + them inside the Get started topic shell. +- [x] Replace `/guides/protect-rest-effect`, `/start/delegate-agent`, and + `/start/verify-receipt` with canonical quickstarts or path pages. +- [x] Add a quickstart index comparing time, runtime, effect boundary, required + state, custody, success, and failure. +- [x] Make every path page select a concrete quickstart rather than restating + concepts without code. +- [x] Rebuild cross-company as an end-to-end journey with identity, authority, + approval, runtime, outcome, and receipt boundaries. +- [x] Move all adoption pages under `/get-started/adoption`, add phase + navigation, and link tested interop/field-lab evidence. +- [x] Preserve global Rust/TypeScript/Python selection across every executable + step. + +## Acceptance + +- No Get started page is a dead end or an orphan. +- Every promised quickstart opens an actual runnable project. +- Every executable journey shows success and its required stable failure. +- A first-time reader can complete one path without leaving Get started. diff --git a/docs/specs/0040/content/content_epic_13.md b/docs/specs/0040/content/content_epic_13.md new file mode 100644 index 00000000..dc02ac06 --- /dev/null +++ b/docs/specs/0040/content/content_epic_13.md @@ -0,0 +1,33 @@ +# Content Epic 13 — Complete Identity and Trust Documentation + +**Depends on:** Content Epics 10–12 and identity/trust release facts. + +## Outcome + +Readers can use Auths identity surfaces independently of capabilities, +approvals, transport, cryptographic suite, or provider implementation. + +## Implementation + +- [x] Build every Identity & trust page in the proposed hierarchy. +- [x] Add an identity-source chooser for raw public keys, OIDC, SPIFFE, and + application resolvers. +- [x] Show standalone public-identity exchange with no authority object. +- [x] Show Ed25519 and P-256 as proof of suite agility and document the custom + suite port without claiming Auths owns all adapters. +- [x] Explain trust roots, issuers, resolver policy, evidence freshness, and + explicit trusted context. +- [x] Document rotation with overlap, rollback, negative fixtures, and no + forced authority migration. +- [x] Add executable verification examples in Rust, TypeScript, and Python. +- [x] Add adversarial examples for unknown suite, mislabelled suite, wrong + root, stale evidence, and verification-method mismatch. +- [x] Keep authority transitions in a labelled Related topics block. + +## Acceptance + +- No Identity landing card substitutes `/integrations`, `/architecture`, or + `/reference` for missing identity content. +- A team can exchange and verify identity bytes without importing authority or + approval APIs. +- Every suite and identity example names who owns trust policy and adapters. diff --git a/docs/specs/0040/content/content_epic_14.md b/docs/specs/0040/content/content_epic_14.md new file mode 100644 index 00000000..de836b7b --- /dev/null +++ b/docs/specs/0040/content/content_epic_14.md @@ -0,0 +1,32 @@ +# Content Epic 14 — Complete Authority Documentation + +**Depends on:** Content Epics 10–13 and native operation/lifecycle facts. + +## Outcome + +The five simple verbs form one progressive path into attenuation, lifecycle, +plans, recovery, verification, receipts, and application profiles. + +## Implementation + +- [x] Build the Authority hierarchy exactly as proposed. +- [x] Give create, delegate, execute, resume, and verify their own conceptual + and executable pages under `/authority`. +- [x] Explain action, resource, time, use, budget, depth, audience, and critical + extension bounds using generated identities and adversarial fixtures. +- [x] Split lifecycle into validity, revocation/status, uses/replay, and budgets. +- [x] Build plan and transaction-bound approval pages with exact-byte and + order-substitution failures. +- [x] Explain sealed commands and the closed gateway without leaking provider + credentials into authority artifacts. +- [x] Build receipts and disclosure as separate integrity and privacy journeys. +- [x] Curate domain profiles and profile-kit construction without coupling + identity, transport, state, custody, or providers. +- [x] Include synchronized Rust/TypeScript/Python examples at each operation. + +## Acceptance + +- Core Authority cards never route to legacy `/start` or `/guides` pages. +- Simple readers see five verbs; advanced readers can descend without changing + vocabulary or semantic owner. +- Every narrowing and lifecycle claim has a fixture-backed failure example. diff --git a/docs/specs/0040/content/content_epic_15.md b/docs/specs/0040/content/content_epic_15.md new file mode 100644 index 00000000..7bc53720 --- /dev/null +++ b/docs/specs/0040/content/content_epic_15.md @@ -0,0 +1,34 @@ +# Content Epic 15 — Complete Agents and MCP Documentation + +**Depends on:** Content Epics 10–14 and agent/plan scenarios. + +## Outcome + +Agent builders can implement a bounded tool, approved plan, multi-agent +handoff, MCP client, or protected MCP server entirely within the Agents +journey. + +## Implementation + +- [x] Replace every current Agents landing destination with a real `/agents/*` + page. +- [x] Build the complete Agents tree in the proposed hierarchy. +- [x] Turn “Delegate one tool” into an executable synchronized quickstart. +- [x] Show the exact delegated scope and one prohibited action on every agent + workflow page. +- [x] Separate MCP client use from protected MCP server construction. +- [x] Add MCP tool-profile and transport-boundary pages; explicitly state that + MCP delivery is not authority. +- [x] Add executable approved-plan and multi-agent examples. +- [x] Document identity composition, skills/plugins, production ownership, and + adversarial testing without bundling them as mandatory components. +- [x] Add failures for widening, prompt substitution, plan substitution, + ambient credentials, transport success, replay, and provider uncertainty. + +## Acceptance + +- The Agents landing contains no generic `/integrations` card labelled MCP. +- Every Agents child renders Agents navigation and meaningful code where the + reader job is implementation. +- A reader can protect an MCP server without first learning unrelated + integration categories. diff --git a/docs/specs/0040/content/content_epic_16.md b/docs/specs/0040/content/content_epic_16.md new file mode 100644 index 00000000..288f9f36 --- /dev/null +++ b/docs/specs/0040/content/content_epic_16.md @@ -0,0 +1,33 @@ +# Content Epic 16 — Complete Production Operations Documentation + +**Depends on:** Content Epics 10–15 and qualified runtime/field-lab commands. + +## Outcome + +An operator can deploy, configure, observe, recover, upgrade, and respond to an +incident using tested procedures with explicit stop conditions. + +## Implementation + +- [x] Build the complete Operations hierarchy and topic navigation. +- [x] Replace one-paragraph operations pages with executable procedures sourced + from isolated local or field-lab scripts. +- [x] Add deployment and configuration indexes for state, custody, trust, + profiles, and provider gateways. +- [x] Add liveness, readiness, dependency, outcome, latency, and redaction + guidance with example signals. +- [x] Add a retry/resume/reconcile/stop decision tree. +- [x] Add verified backup/restore and upgrade/rollback exercises that preserve + replay, budget, recovery, and receipts. +- [x] Split each incident class into its own runbook page with tested commands, + expected observations, stop conditions, and evidence retention. +- [x] Add provider-unknown and receipt-disclosure security warnings that cannot + be omitted by page configuration. + +## Acceptance + +- No operational landing card substitutes generic Architecture, Developers, + Assurance, or starter pages for an Operations procedure. +- Every command is scenario-owned and tested; no hand-copied commands exist. +- No runbook recommends blind retry after provider uncertainty. +- An operator can navigate the complete Operations tree from every page. diff --git a/docs/specs/0040/content/content_epic_17.md b/docs/specs/0040/content/content_epic_17.md new file mode 100644 index 00000000..d382bc57 --- /dev/null +++ b/docs/specs/0040/content/content_epic_17.md @@ -0,0 +1,33 @@ +# Content Epic 17 — Complete Developer, Integration, and Extension Documentation + +**Depends on:** Content Epics 10–16 and generated SDK/Runtime/CLI contracts. + +## Outcome + +Developers can choose an SDK, call the runtime, use the CLI, test failures, +integrate adjacent systems, extend ports, and inspect releases without leaving +the Developers hierarchy prematurely. + +## Implementation + +- [x] Build the complete Developers hierarchy in the proposed tree. +- [x] Replace the Quickstarts card with a real `/developers/quickstarts` index + that clearly hands off to Get started projects. +- [x] Build Rust, TypeScript, Python, and parity orientation pages with + synchronized code and exact reference handoffs. +- [x] Add substantive Runtime API and CLI orientation pages with installation, + first call, outcomes, error handling, and source-at-release. +- [x] Build testing and error hubs around generated outcomes and fixtures. +- [x] Move integration composition under `/developers/integrations` and give + every integration an ownership matrix, code, failure modes, and limits. +- [x] Add extension-kit, example catalog, versioning, changelog, and support + matrix pages. +- [x] Link exact Reference symbols or endpoints; never use a generic reference + landing as a substitute. + +## Acceptance + +- Every Developers landing card first reaches a Developers-owned index page. +- SDK and Runtime reference remain generated and visually consistent. +- Integration pages contain real composition guidance and executable code. +- `/reference/cli.md` and every other page/section Markdown target exist. diff --git a/docs/specs/0040/content/content_epic_18.md b/docs/specs/0040/content/content_epic_18.md new file mode 100644 index 00000000..2704cab7 --- /dev/null +++ b/docs/specs/0040/content/content_epic_18.md @@ -0,0 +1,31 @@ +# Content Epic 18 — Complete Reference and Assurance Utilities + +**Depends on:** Content Epics 10–17 and Platform Epics P8–P10. + +## Outcome + +Reference and Assurance become exact cross-cutting utilities, not generic pages +used to paper over missing product-section content. + +## Implementation + +- [x] Build a complete Reference navigation for SDK, Runtime API, CLI, + profiles, errors, schemas, evidence, and manifest. +- [x] Generate every signature, endpoint, flag, default, error, version, and + evidence status from the release bundle. +- [x] Give CLI, profiles, errors, schemas, and evidence the same depth and + navigation quality as SDK and Runtime reference. +- [x] Build Assurance navigation for semantics, authority, execution, + disclosure, cross-language, formal, adversarial, supply-chain, and limits. +- [x] Render claim statement, status, evidence checksum, reproduction, scope, + and limitation from stable claim identities. +- [x] Link each product security statement to an exact claim page. +- [x] Ensure HTML, page Markdown, section Markdown, manifests, and agent + discovery expose the same release identity. + +## Acceptance + +- No utility page is an orphan or a one-paragraph placeholder. +- Every generated fact has exactly one owner and one source-at-release link. +- Withdrawing evidence changes or blocks every affected claim page. +- Reference and Assurance links are exact, not generic topic handoffs. diff --git a/docs/specs/0040/content/content_epic_19.md b/docs/specs/0040/content/content_epic_19.md new file mode 100644 index 00000000..fbea49ff --- /dev/null +++ b/docs/specs/0040/content/content_epic_19.md @@ -0,0 +1,46 @@ +# Content Epic 19 — Full-Site Content and Link Qualification + +**Depends on:** Content Epics 10–18 and Platform Epic P11. + +## Outcome + +The failures recorded in the site audit become impossible to reintroduce. + +## Implementation + +- [x] Crawl every canonical HTML page and every rendered internal link on the + exact current docs head. +- [x] Fail on orphan pages, missing parents, wrong active nav, broken + breadcrumbs, missing previous/next, or duplicate canonical routes. +- [x] Validate landing-card intent: primary cards must target descendants; + cross-topic cards require an explicit Related topics label. +- [x] Enforce page-type content contracts from Content Epic 11. +- [x] Fail implementation guides with no qualified code and runbooks with no + tested commands. +- [x] Fail generic tested-scenario links that do not resolve to the exact + scenario page and step. +- [x] Verify every HTML, page Markdown, section Markdown, download, search, + sitemap, discovery, and manifest target. +- [x] Run deterministic unfamiliar-reader journey proxies for each top-level + section. Moderated reader research remains a release activity and is named + as a limit rather than being represented as automated evidence. +- [x] Publish a release report listing pages, links, orphans, code coverage, + procedure coverage, accessibility, responsive checks, and known limits. + +## Acceptance + +- Zero orphan pages and zero broken or misleading landing cards. +- Every non-landing page has correct topic navigation. +- Every public link resolves to the promised reader job. +- The six unfamiliar-reader journeys complete without facilitator help. +- The audit report is generated from the deployed candidate and exact source + heads, not a stale fixture. + +## Qualification record + +`npm run test:site` builds the report at +`outputs/site-qualification-report.json`. It evaluates the built deployment +candidate against the current release contract and records the exact docs head. +The report distinguishes structural accessibility and responsive stylesheet +qualification from browser-level assistive-technology checks and moderated +reader research. diff --git a/docs/specs/0040/content/content_epic_2.md b/docs/specs/0040/content/content_epic_2.md new file mode 100644 index 00000000..d785b052 --- /dev/null +++ b/docs/specs/0040/content/content_epic_2.md @@ -0,0 +1,109 @@ +# Content Epic 2 — Getting Started and the Integration Chooser + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Status:** Complete in `auths-docs` commit `21dec44`. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epic 1, and Platform +Epic P6. + +**Ownership:** This epic owns reader questions, recommendation policy, and +public explanations. Platform P6 owns chooser and guide models; generated facts +and scenario code remain bundle-owned. + +## Outcome + +A reader with no Auths knowledge can identify the correct integration mode in +under three minutes and reach a qualified first build without learning the +entire authority model. + +## Current problem + +The existing start experience privileges one REST guide and exposes SDK/runtime +formats before the reader has chosen deployment, trust, or effect boundaries. +Auths needs several opinionated first paths, not one universal quickstart. + +Stripe uses prerequisites, audience exits, product choosers, and named outcome +recipes before deep implementation. [Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-2--tours-prerequisites-testing-and-outcome-recipes) + +## Journey + +```text +What are you protecting? + | + +-- local application effect ------> local SDK quickstart + +-- service/runtime effect --------> production runtime quickstart + +-- delegated agent action --------> agent delegation quickstart + +-- cross-company operation -------> portable authority quickstart + +-- evidence only -----------------> offline verification quickstart + +-- custom protocol/profile -------> extension path +``` + +## Required pages + +| Route | Type | Purpose | +|---|---|---| +| `/get-started` | Topic landing | Recommended first path and prerequisites | +| `/get-started/choose` | Chooser | Select integration by effect, deployment, trust, and operator needs | +| `/get-started/prerequisites` | Prerequisite catalog | Runtime, language, keys, state, trust, and sandbox requirements | +| `/get-started/local` | Outcome recipe | Protect one local application effect | +| `/get-started/runtime` | Outcome recipe | Submit one exact effect to the open runtime | +| `/get-started/agent` | Outcome recipe | Delegate one tool to one agent | +| `/get-started/cross-company` | Outcome recipe | Authorize across independent identity systems | +| `/get-started/verify` | Outcome recipe | Verify proof or receipt without executing | +| `/get-started/evaluate` | Evaluation guide | Run deterministic fixtures and compare outcomes | + +## Chooser dimensions + +Parse the reader's choices into a closed recommendation model: + +- effect location: in-process, local service, remote service, provider; +- actor: person, workload, agent, organization; +- identity/trust source: raw key, OIDC, SPIFFE, application resolver, other; +- authority need: direct, delegated, approved plan, verification only; +- state need: none, replay, budget, durable recovery; +- custody: development signer, application signer, KMS/HSM port; +- integration ownership: Auths-maintained profile or application-owned profile; +- operational posture: evaluation, self-hosted production, integration author. + +The chooser returns one primary route, up to two alternatives, and the reasons +for the recommendation. It never generates authority or collects credentials. + +## Implementation steps + +- [ ] Author the deterministic recommendation table against P6's chooser + schema. +- [ ] Author prerequisites with early exits for non-developers, SDK users, + runtime operators, agent builders, and integration authors. +- [ ] Write the five outcome recipes using the same actors and one comprehensible + incident/reporting domain. +- [ ] Link every recipe to a Content Epic 4 tested project. +- [ ] State what the reader will produce, how long it should take, and what is + deliberately excluded at the top of each path. +- [ ] End every path with success evidence, one fail-closed mutation, and next + steps into concepts, operations, and reference. +- [ ] Add a “bring your existing identity” branch without implying that Auths + owns identity providers or cryptographic adapters. +- [ ] Declare page dependencies so P6 can generate affected-page relationships. + +## Acceptance criteria + +- Five unfamiliar developers choose the intended route from five fixture + scenarios with no facilitator explanation. +- No first path requires capabilities, approvals, Iroh, a hosted runtime, or a + specific identity suite unless that path's outcome needs it. +- Each route distinguishes local evaluation from production requirements. +- Every route exposes exactly one primary outcome and one adversarial failure. +- All links resolve to stable identities and canonical Markdown exists. + +## Validation + +```text +npm run test:chooser +npm run test:content +npm run test:links +npm run test:markdown +npm run test:usability-fixtures +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_3.md b/docs/specs/0040/content/content_epic_3.md new file mode 100644 index 00000000..bd433185 --- /dev/null +++ b/docs/specs/0040/content/content_epic_3.md @@ -0,0 +1,123 @@ +# Content Epic 3 — Semantic Tours and Lifecycle Concepts + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Status:** Complete in `auths-docs` commit `c2fe2ec`. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epic 1, and Platform +Epic P6. + +**Ownership:** This epic owns conceptual teaching and accessible conceptual +diagrams. Lifecycle states, outcome names, trust facts, and evidence are +embedded from the release bundle rather than redefined in prose. + +## Outcome + +Readers understand the Auths model, boundaries, and state transitions before +they encounter low-level APIs. + +## Current problem + +Auths has unusually precise semantics, but its explanation is fragmented across +architecture, specifications, demos, and reference terminology. A reader can +learn how to call a method without understanding why the authority, execution, +or recovery types exist. + +Stripe uses API tours and lifecycle pages to explain relationships and state +independently from quickstarts and reference. [Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-3--product-choice-interactive-quickstarts-and-lifecycle-concepts) + +## Required tours + +### Auths in fifteen minutes + +Teach the five nouns and five verbs using one bounded operation: + +```text +actor --create--> authority --delegate--> narrower authority + | | + +-- exact action ----------------------+ + | + execute + | + denied | indeterminate | recoverable | completed + | + receipt --verify--> inert decision +``` + +### Identity and trust + +Explain identity material, authentication evidence, trust roots, resolvers, +cryptographic suites, and the boundary between proving who signed and deciding +what that signer may do. Show Ed25519 and P-256 only as proof of replaceability. + +### Authority lifecycle + +Explain authoring, commitment, attenuation, delegation depth, critical +extensions, expiry, revocation, use and budget state, and exhaustion. + +### Execution lifecycle + +Explain parse, verify, authorize, reserve, seal, gateway entry, provider +observation, receipt, recoverable reference, resume, and terminal outcomes. + +### Approval-bound plans + +Explain exact-plan commitment, threshold or ordered approval, substitution +resistance, cancellation, partial/unknown provider outcomes, and why approval +alone cannot execute. + +### Receipt and disclosure lifecycle + +Explain decision versus execution receipts, opaque/summary/full disclosure, +authorization for disclosure, sensitive detail, and offline verification. + +## Page contract + +Each tour or lifecycle page contains: + +1. the problem the primitive solves; +2. a horizontal overview diagram and text equivalent; +3. states or components with stable identities; +4. invariants in plain language; +5. a happy path and at least three failure branches; +6. “use this when” and “do not use this when”; +7. links to tested quickstarts and generated reference; and +8. versioned evidence links for security claims. + +## Implementation steps + +- [ ] Add stable page and section identities for all six tours. +- [ ] Compose the registered P6/P9 `Tour`, `Lifecycle`, `Invariant`, and + `FailurePath` components; do not implement alternate renderers here. +- [ ] Reference release-bundle state, outcome, profile, and error identities in + page dependencies. +- [ ] Author the six tours using one consistent example domain. +- [ ] Author accessible diagram source and text equivalents for P5's build-time + renderer; prohibit browser Mermaid. +- [ ] Add explicit composition diagrams showing identity, authority, transport, + state, custody, and provider ports as independently replaceable. +- [ ] Review every invariant against Rust-owned semantics and frozen fixtures. +- [ ] Declare related-reference links for P8 to resolve from generated symbols. + +## Acceptance criteria + +- No tour includes an invented public symbol or hand-authored outcome enum. +- A reader can explain identity versus authority, approval versus execution, + transport versus authorization, and recoverable versus retry after completing + the tours. +- Every diagram has an equivalent ordered text description. +- Mutation, replay, expiry, widening, revocation, and provider-unknown appear in + at least one lifecycle path. +- HTML and canonical Markdown carry the same semantic content. + +## Validation + +```text +npm run test:content +npm run test:diagrams +npm run test:evidence-links +npm run test:markdown +npm run test:a11y +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_4.md b/docs/specs/0040/content/content_epic_4.md new file mode 100644 index 00000000..aed84c64 --- /dev/null +++ b/docs/specs/0040/content/content_epic_4.md @@ -0,0 +1,127 @@ +# Content Epic 4 — Outcome Quickstarts and Tested Projects + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epics 2–3, and Platform +Epic P7. + +**Ownership:** This epic owns quickstart sequencing, explanation, and reader +transitions. P7 owns executable source, commands, fixtures, and normalized +results. Public MDX selects scenario identities and never copies their code. + +## Outcome + +Every recommended Auths path has a runnable, downloadable, cross-language +project that produces one observable success and demonstrates fail-closed +behavior. + +## Current problem + +The current site renders representative snippets and labels scenarios as +tested, but the documentation repository does not yet install and execute every +displayed Rust, TypeScript, and Python project. Static snippets cannot prove a +reader can reproduce the workflow. + +Stripe's interactive quickstarts synchronize language/framework choices, +numbered steps, working samples, downloads, and text alternatives. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-3--product-choice-interactive-quickstarts-and-lifecycle-concepts) + +## Launch quickstarts + +| Stable scenario | Route | Success | Required failure | +|---|---|---|---| +| `auths.scenario.local-rest-effect/1` | `/quickstarts/local-rest-effect` | One exact REST-shaped effect completes | Mutated bytes denied | +| `auths.scenario.runtime-effect/1` | `/quickstarts/runtime-effect` | Open runtime returns a completed receipt | Exact replay denied | +| `auths.scenario.agent-delegation/1` | `/quickstarts/agent-delegation` | Agent calls one delegated tool | Widening rejected | +| `auths.scenario.approved-plan/1` | `/quickstarts/approved-plan` | Exact approved plan completes in order | Substituted plan rejected | +| `auths.scenario.offline-verification/1` | `/quickstarts/offline-verification` | Proof and receipt verify offline | Wrong context denied | +| `auths.scenario.recovery/1` | `/quickstarts/recovery` | Recoverable execution resumes once | Fresh retry prohibited | +| `auths.scenario.identity-swap/1` | `/quickstarts/identity-swap` | Same workflow passes with two suites | Mislabelled suite rejected | + +## Project structure + +```text +examples// +├── scenario.json +├── rust/ +│ ├── Cargo.toml +│ └── src/main.rs +├── typescript/ +│ ├── package.json +│ └── src/main.ts +├── python/ +│ ├── pyproject.toml +│ └── main.py +├── expected/ +│ ├── completed.json +│ └── failure.json +└── README.md +``` + +Every runner installs immutable release candidates in an empty consumer. It +captures bounded normalized output, redacts environment-specific fields, and +compares semantic outcomes across languages. + +## Quickstart UX + +```text ++----------------------+---------------------------+---------------------------+ +| Steps | Meaning | Tested source / result | +| 1 Install | What this step changes | Rust | TypeScript | Python| +| 2 Compose | Security boundary | source | +| 3 Create | Expected state |---------------------------| +| 4 Execute | | normalized result | +| 5 Break safely | | | ++----------------------+---------------------------+---------------------------+ +``` + +Required controls: + +- global language selection; +- optional application framework selection only when the project truly differs; +- numbered progress and deep links; +- copy, open canonical Markdown, download exact project, and source-at-release; +- tested release identity and fixture digest; +- expected duration and prerequisites; +- text-only alternative with identical semantic steps; and +- next steps into tours, operations, and reference. + +## Implementation steps + +- [x] Select the seven required scenario identities from P7 and report missing + scenarios as platform dependencies. +- [x] Author each quickstart's outcome, prerequisites, transitions, explanation, + failure path, and next steps. +- [x] Assemble displayed steps exclusively with P7 scenario components. +- [x] Keep Rust, TypeScript, and Python at the same semantic step while allowing + idiomatic explanation around each projection. +- [x] Link deterministic archives and source-at-release provenance produced by + P7. +- [x] Review normalized results for plain-language comprehensibility without + copying result payloads into MDX. +- [x] Prohibit executable MDX fences and copied examples. +- [x] Record missing failure coverage against the owning P7 scenario rather + than patching code in the content lane. + +## Acceptance criteria + +- Every displayed executable line comes from a project that ran successfully. +- Each language produces the same normalized semantic outcome. +- Failure demonstrations fail for the intended stable reason. +- A clean machine can download and run each project using documented commands. +- Switching language never changes step meaning or skips a security boundary. +- Quickstart HTML, text view, Markdown, and archive name the same release and + scenario digest. + +## Validation + +```text +npm run examples:prepare -- --bundle +npm run examples:run +npm run examples:compare +npm run test:quickstarts +npm run test:downloads +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_5.md b/docs/specs/0040/content/content_epic_5.md new file mode 100644 index 00000000..b2738efb --- /dev/null +++ b/docs/specs/0040/content/content_epic_5.md @@ -0,0 +1,137 @@ +# Content Epic 5 — Developer Resources and Generated Reference + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Depends on:** [Content Epic 0](./epic_0.md) and Platform Epics P4 and P8. + +**Ownership:** This epic owns developer landing curation and explanatory +introductions. P8 exclusively owns generated reference pages, signatures, +endpoint inventories, errors, versions, and fact templates. + +## Outcome + +Developers can move from ecosystem orientation to exact Rust, TypeScript, +Python, Runtime API, CLI, schema, error, and evidence contracts without +encountering hand-maintained drift. + +## Current problem + +The current SDK and Runtime API pages prove the intended visual layout, but +their content models are still partly hard-coded in the docs repository. The +CLI, error catalog, schema reference, version policy, source links, and complete +cross-language SDK journey are absent or shallow. + +Stripe separates Developer Resources, SDK catalogs, API catalogs, cross-language +SDK guides, CLI reference, errors, and versioning. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-5--sdks-cli-agents-failures-and-assurance) + +## Developer landing + +`/developers` groups: + +- install and local environment; +- Rust, TypeScript, and Python SDKs; +- Runtime API; +- CLI; +- agent and MCP tooling; +- testing and deterministic fixtures; +- errors and closed outcomes; +- integrations and extension kits; +- versioning, changelog, and release support; +- assurance and source code. + +## Reference hierarchy + +```text +/reference +├── /sdk +│ ├── /rust +│ ├── /typescript +│ └── /python +├── /runtime-api +├── /cli +├── /profiles +├── /errors +├── /schemas +├── /evidence +└── /manifest.json +``` + +## Cross-language SDK guide + +The main SDK guide synchronizes language across: + +1. installation and supported runtime; +2. explicit integration composition; +3. `create`; +4. `delegate`; +5. `execute`; +6. `resume`; +7. `verify`; +8. outcome and receipt inspection; +9. error handling; +10. testing; +11. advanced/profile-specific entry points; and +12. source and release provenance. + +Rust may expose lower-level native components where the product facade differs, +but the page must label that distinction and preserve semantic equivalence. + +## Generated fact ownership + +| Fact | Sole owner | +|---|---| +| Rust signatures/docs | installed Rustdoc/bounded export | +| TypeScript exports/signatures/docs | installed declarations and API snapshot | +| Python signatures/docs | installed wheel, stubs, runtime metadata | +| Runtime endpoints/limits/content types | compiled Rust runtime export | +| CLI commands/flags/defaults | compiled CLI command graph | +| Profiles and stable errors | frozen Rust registries | +| Schemas and fields | release schemas | +| Evidence/claim status | release evidence graph | + +Authored content may explain a fact but cannot restate its signature, version, +default, or inventory as source truth. + +## Implementation steps + +- [x] Audit P4/P8 bundle coverage for every fact-owner row and report extractor + gaps to the platform lane. +- [x] Remove hard-coded SDK operations and Runtime endpoints from authored + content. +- [x] Author the developer landing and curate its generated reference catalogs. +- [x] Author the cross-language SDK orientation and link each operation by + stable identity. +- [x] Curate explanatory introductions and related journeys for Runtime API, + CLI, errors, profiles, schemas, and evidence. +- [x] Author compatibility, preview-channel, and prelaunch policy explanation + around generated support facts. +- [x] Review P8's three-column SDK and Runtime API renderings for reader + comprehension without editing generated pages. +- [x] Resolve every authored dependency reported by P8's contract diff; never + suppress stale or missing projections with copied prose. + +## Acceptance criteria + +- Changing a public argument or endpoint in `auths-proof` updates the correct + page or fails the source PR with an exact dependency report. +- No maintained public symbol is missing its generated reference projection. +- SDK and Runtime API pages share navigation, section actions, sticky code, + outcome rendering, responsive behavior, and Markdown parity. +- CLI reference is exhaustive and generated from executable command metadata. +- Error pages distinguish denied, indeterminate, recoverable, provider-unknown, + invalid input, and internal failures without collapsing them into exceptions. +- A fresh docs build does not mutate source files. + +## Validation + +```text +npm run reference:build -- --bundle +npm run reference:check +npm run test:contract-diff +npm run test:reference +npm run test:markdown +npm run test:search +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_6.md b/docs/specs/0040/content/content_epic_6.md new file mode 100644 index 00000000..1022d57c --- /dev/null +++ b/docs/specs/0040/content/content_epic_6.md @@ -0,0 +1,116 @@ +# Content Epic 6 — Agents, MCP, and Integrations + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epics 3–5, and Platform +Epic P9. + +**Ownership:** This epic owns composition guidance, recommendations, and +integration narratives. P9 owns typed ownership matrices and fact-backed +components; adapter inventories and supported capabilities remain generated. + +## Outcome + +Agent builders and integration owners can understand which Auths components are +independent, choose a composition, and implement bounded agent authority without +assuming that identity, transport, capability, approval, or provider adapters +are mandatory bundles. + +## Current problem + +Auths' flexibility is a major advantage but can look like a single complex +system when content introduces all components together. Existing demos prove +composition, yet the docs lack distinct paths for using an MCP client, building +a protected MCP server, delegating to an agent, importing policy/identity +context, and authoring adapters. + +Stripe's agent pages separate developer tools, MCP, agent skills, billing, and +commerce, then explain independent combinations. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-5--sdks-cli-agents-failures-and-assurance) + +## Required landings and guides + +| Route | Purpose | +|---|---| +| `/agents` | Choose an agent use case | +| `/agents/how-auths-works` | Architecture and independent composition | +| `/agents/delegate-one-tool` | First bounded delegation | +| `/agents/approved-plan` | Exact multi-step plan with approvals | +| `/agents/multi-agent` | Attenuated handoff across agents | +| `/agents/mcp-client` | Use Auths tooling from an agent harness | +| `/agents/protect-mcp-server` | Build an MCP server with closed execution | +| `/agents/skills` | Maintained skills/plugins and installation | +| `/integrations` | Composition chooser and ownership matrix | +| `/integrations/identity-trust` | OIDC, SPIFFE, raw keys, application resolvers | +| `/integrations/policy` | Cedar, OPA, ReBAC evidence/context composition | +| `/integrations/cloud` | Provider IAM and closed credential gateways | +| `/integrations/transport` | HTTPS, Iroh, queues, and application transport | +| `/integrations/capabilities` | UCAN, Biscuit, macaroons, imported authority | +| `/integrations/profile-kit` | Application-owned profile construction | + +## Composition model + +```text +identity/trust evidence ----+ +policy/context evidence -----+--> Auths verification and authority +imported capability ---------+ | + v +transport ------------------------> sealed command delivery + | +state/custody --------------------> closed runtime gateway + | +provider adapter -----------------> application effect +``` + +Each guide includes a table with rows `Auths supplies`, `application supplies`, +`external system supplies`, `state required`, `secrets involved`, `offline +verification`, and `failure ownership`. + +## Agent skills policy + +- Maintained plugins/skills are the recommended path. +- Installation instructions are generated from versioned manifests. +- Manual prompt copying is a fallback with explicit update and provenance risk. +- Skills may explain and invoke public Auths tools but never contain credentials + or bypass runtime authorization. +- Agent documentation distinguishes proposing, approving, authorizing, + executing, observing, and verifying. + +## Implementation steps + +- [x] Declare page identities against P9's integration ownership schema. +- [x] Author the agent landing and architecture page before individual guides. +- [x] Build the seven agent/MCP guides over Content Epic 4 scenarios. +- [x] Build the integration chooser and six composition guides. +- [x] Curate generated adapter/profile inventories from release topology. +- [x] Add “Auths with” links to interoperability fixtures rather than unsupported + competitive claims. +- [x] Author install explanations and safety boundaries around P4's versioned + skill/plugin manifests. +- [x] Add adversarial content examples for widening, prompt substitution, + approval substitution, transport success, ambient credential access, and + unknown provider outcomes. + +## Acceptance criteria + +- No page implies that Iroh requires Auths authority, that identity requires + capabilities, or that approval alone authorizes an effect. +- A reader can select and implement identity, policy, transport, custody, state, + and provider components independently. +- MCP client use and protected MCP server construction are separate journeys. +- Every agent guide shows the exact delegated scope and one prohibited action. +- Maintained skills resolve to a release and pass secret/content scans. +- TypeScript and Python workflows remain semantically identical. + +## Validation + +```text +npm run test:content +npm run test:integration-matrix +npm run test:agent-scenarios +npm run test:skills +npm run test:security-copy +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_7.md b/docs/specs/0040/content/content_epic_7.md new file mode 100644 index 00000000..0ff562da --- /dev/null +++ b/docs/specs/0040/content/content_epic_7.md @@ -0,0 +1,135 @@ +# Content Epic 7 — Adoption and Migration + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epics 2–6, and Platform +Epic P9. + +**Ownership:** This epic owns migration strategy and reader guidance. Product +support, integration capabilities, commands, and conformance results resolve +from generated facts or tested scenarios. + +## Outcome + +Teams can introduce Auths beside existing identity, credential, IAM, policy, +capability, and signed-request systems, prove value on one bounded effect, and +cut over without a flag day. + +## Current problem + +Auths documentation explains the target model but does not yet give an +implementation owner a safe migration process from existing authorization and +credential systems. Without an adoption path, a strong protocol can appear to +require replacing the identity provider, policy engine, cloud IAM, and runtime +simultaneously. + +Stripe's migration content separates overview, planning, coordination, +sensitive-data procedures, field-level requirements, output mapping, and +post-migration updates. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-1--global-landings-catalogs-and-depth-transitions) + +## Adoption principles + +- Compose before replacing. +- Start with one exact high-value effect. +- Reuse existing identity and policy evidence where safe. +- Keep provider credentials behind the existing trusted gateway first. +- Compare decisions in shadow mode before enforcing. +- Preserve denied, indeterminate, recoverable, and provider-unknown outcomes. +- Make rollback a documented state transition, not an emergency improvisation. +- Never export or copy secret key material into documentation tooling. + +## Required pages + +| Route | Reader job | +|---|---| +| `/get-started/adopt` | Choose an adoption path | +| `/adopt/plan` | Inventory effects, actors, credentials, policies, and state | +| `/adopt/signed-requests` | Add exact authority to an existing signed request | +| `/adopt/oauth-oidc` | Retain login/session identity and add bounded effect authority | +| `/adopt/api-keys` | Move from ambient bearer access to closed gateway execution | +| `/adopt/cloud-iam` | Compose workload/IAM identity with exact Auths authority | +| `/adopt/policy-engines` | Use Cedar, OPA, or ReBAC decisions as explicit context | +| `/adopt/capabilities` | Import or bridge UCAN, Biscuit, or macaroon authority | +| `/adopt/approvals` | Bind existing approval workflows to exact plan bytes | +| `/adopt/shadow-mode` | Compare Auths with current enforcement without effects | +| `/adopt/cutover` | Enforce, observe, and rollback one protected effect | + +## Migration phases + +```text +inventory -> model -> verify in shadow -> compare -> enforce one effect + -> observe -> expand deliberately + | + +--> rollback to previous gateway while preserving evidence +``` + +### Inventory + +Record actor sources, effect entry points, existing scopes/roles, provider +credential location, approval systems, replay/idempotency behavior, audit data, +and unknown-outcome handling. Do not collect credential values. + +### Model + +Map one effect to canonical action bytes, authority limits, trust evidence, +state requirements, gateway ownership, expected outcomes, and receipt +disclosure. + +### Shadow + +Run effect-free Auths verification beside existing enforcement. Store bounded +decision comparison records; never call the provider from shadow mode. + +### Enforce + +Place the existing provider client behind the closed gateway and require an +opaque verified command. Start with one route or operation and an explicit +rollback switch. + +### Expand + +Add actors, effects, delegation, approvals, or transports one dimension at a +time. Every expansion requires new fixtures and operational evidence. + +## Implementation steps + +- [x] Author a privacy-safe adoption inventory form against P9's registered + schema. +- [x] Author the adoption chooser and phased planning guide. +- [x] Build the nine source-system composition guides with ownership matrices. +- [x] Select shadow comparison fixtures from the interoperability repository and + record missing fixtures as platform dependencies. +- [x] Explain generated bounded comparison and migration receipts without + copying secrets or raw business payloads. +- [x] Link one qualified end-to-end cutover/rollback field lab; do not reproduce + its commands or results in MDX. +- [x] Document key rotation and trust-root changes without requiring identity + migration. +- [x] Add mapping-output review and reconciliation procedures. +- [x] Link every competitive claim to the evidence-based research repository. + +## Acceptance criteria + +- Every guide preserves the existing system's legitimate role and states where + Auths overlaps, composes, or adds operational cost. +- No guide requires replacing an IdP, policy engine, transport, or cloud IAM to + protect the first effect. +- Shadow mode cannot mint an executable authorization object or call a provider. +- Cutover includes preconditions, observable success, fail-closed cases, + rollback, and reconciliation. +- Migration records contain commitments and classifications, not credentials or + unnecessary business payloads. + +## Validation + +```text +npm run test:adoption-content +npm run test:integration-matrix +npm run test:shadow-fixtures +npm run test:privacy +npm run test:links +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_8.md b/docs/specs/0040/content/content_epic_8.md new file mode 100644 index 00000000..24abf6ad --- /dev/null +++ b/docs/specs/0040/content/content_epic_8.md @@ -0,0 +1,143 @@ +# Content Epic 8 — Operations, Testing, Failure, and Recovery + +> **Status revoked by rendered-site audit.** Requalify through Content Epics +> 10–19; existing checked tasks record prior implementation, not completion. + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epics 4–7, and Platform +Epic P9. + +**Ownership:** This epic owns operational explanation and procedure ordering. +Commands, configuration, error inventories, outcomes, limits, and evidence are +generated or scenario-backed; CI and deployment mechanics belong to P11. + +## Outcome + +Operators can deploy the open Auths runtime, test realistic outcomes, observe +its boundaries, recover uncertain work safely, upgrade it, and respond to +incidents without relying on tribal knowledge. + +## Current problem + +Auths has production-shaped runtime, custody, state, observability, and recovery +surfaces, but the public documentation does not yet form a complete operator +journey. Failure knowledge is spread across code, specs, demos, and error +registries. + +Stripe publishes scenario-based testing, action-oriented error handling, and +ordered configuration procedures with explicit operating modes and boundaries. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-2--tours-prerequisites-testing-and-outcome-recipes), +[configuration evidence](./STRIPE_CONTENT_RESEARCH.md#batch-4--product-landings-design-decisions-and-operational-boundaries) + +## Operations information architecture + +```text +/operations +├── evaluate locally +├── deploy the open runtime +├── configure durable state +├── configure custody +├── configure trust and profiles +├── configure provider gateways +├── observability and SLOs +├── backup and restore +├── recovery and reconciliation +├── upgrade and rollback +├── receipt retention and disclosure +└── incident response runbooks +``` + +## Testing catalog + +`/developers/testing` exposes deterministic recipes for: + +- successful authorization and execution; +- malformed or oversized input; +- invalid signature and unknown suite; +- untrusted identity evidence; +- action-byte mutation; +- attenuation widening; +- expiry and not-yet-valid authority; +- revocation; +- replay, use exhaustion, and budget exhaustion; +- approval substitution and insufficient threshold; +- denied, indeterminate, and internal failure; +- provider timeout before submission; +- provider-unknown after possible submission; +- recoverable resume and invalid fresh retry; +- receipt tampering and unauthorized disclosure; and +- state-store, custody, and trust-resolver unavailability. + +Each recipe names the fixture, expected stable outcome/error, permitted retry or +resume action, and observable evidence. + +## Failure hub + +`/developers/errors` begins with the closed outcome model, then groups generated +stable errors by reader response: + +| Class | Operator/developer response | +|---|---| +| denied | Change authority, trust, or request; do not retry unchanged | +| indeterminate | Investigate missing evidence or unavailable decision input | +| recoverable | Observe and resume the same execution reference | +| provider-unknown | Reconcile provider state before any retry | +| invalid input | Correct parsing/size/schema failure before resubmission | +| internal | Preserve correlation evidence and escalate | + +Every generated error page includes meaning, safe response, unsafe response, +language examples, related fixtures, runbook, source-at-release, and version. + +## Runbook contract + +Every procedure contains: + +1. ownership and severity; +2. preconditions and required access; +3. safety and secret-handling warnings; +4. exact commands from tested scripts; +5. expected observations after each step; +6. stop conditions; +7. rollback or resume path; +8. reconciliation and evidence retention; and +9. escalation information. + +## Implementation steps + +- [x] Author the operations landing and deployment-mode chooser. +- [x] Author procedures around tested P7/P9 commands for runtime, state, + custody, trust, gateway, telemetry, backup/restore, upgrade, and rollback. +- [x] Curate the generated testing catalog from adversarial and differential + fixtures. +- [x] Curate the generated failure hub from stable error and outcome registries. +- [x] Add decision trees for retry, resume, reconcile, and stop. +- [x] Add observable metrics, logs, traces, health checks, and SLO examples + without leaking authority or receipt contents. +- [x] Build incident runbooks for state loss, signer outage, trust-root error, + provider uncertainty, receipt disclosure, and compromised credentials. +- [x] Require every published command to resolve to an isolated local or + field-lab scenario identity. +- [x] Explain sanitized sample evidence produced by the owning scenario. + +## Acceptance criteria + +- No runbook recommends blind retry after a provider-unknown outcome. +- Every command is sourced from an executable checked script. +- Secret values, raw sealed commands, and full receipts are absent from logs and + examples unless an explicitly authorized disclosure lesson requires them. +- Operators can distinguish liveness, readiness, dependency degradation, and + semantic authorization failure. +- Backup/restore and rollback exercises preserve replay, budget, recovery, and + receipt invariants. +- All supported failure classes have a generated error page and a tested recipe. + +## Validation + +```text +npm run test:runbooks +npm run test:error-catalog +npm run test:failure-recipes +npm run test:observability-redaction +npm run test:links +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/content_epic_9.md b/docs/specs/0040/content/content_epic_9.md new file mode 100644 index 00000000..d967ef34 --- /dev/null +++ b/docs/specs/0040/content/content_epic_9.md @@ -0,0 +1,162 @@ +# Content Epic 9 — Assurance Narrative and Editorial Governance + +**Depends on:** [Content Epic 0](./epic_0.md), Content Epics 1–8, and Platform +Epics P9–P11. + +**Ownership:** This epic owns assurance explanation, editorial claim selection, +limitations, and content-review policy. P9 owns fact-backed assurance +components, P10 owns machine rendering, and P11 owns qualification and release +orchestration. + +## Outcome + +Every public Auths claim is versioned, evidenced, limited, searchable, available +to humans and agents, and prevented from drifting away from the released +software. + +## Current problem + +Auths has substantial formal, adversarial, differential, supply-chain, and live +evidence, but the docs currently summarize assurance more readily than they let +a reader trace an exact claim to current evidence. Content completeness and +usability also need explicit editorial requirements that P11 can enforce +through one release gate. + +Stripe separates its security narrative from product instructions and publishes +machine-readable page actions and discovery surfaces across the documentation. +[Research evidence](./STRIPE_CONTENT_RESEARCH.md#batch-5--sdks-cli-agents-failures-and-assurance) + +## Assurance model + +```text +claim -> stable identity -> applicable release -> evidence -> reproduction + | | + +-------------- limitation and scope ------------+ +``` + +### Required assurance sections + +- protocol semantics and canonicalization; +- attenuation and delegation; +- critical extensions; +- replay, use, budget, and lifecycle state; +- approval and plan commitment; +- sealed commands and closed gateways; +- receipt integrity and bounded disclosure; +- cryptographic, identity, transport, and provider agility; +- Rust/TypeScript/Python differential evidence; +- formal models and their exact scope; +- fuzzing and adversarial fixtures; +- supply-chain provenance, SBOM, SLSA, and release reproducibility; +- production field evidence and explicit limitations; +- supported runtimes and compatibility policy; and +- security reporting and outside-review status. + +## Claim page contract + +Every claim page includes: + +- stable claim identity; +- plain-language statement; +- normative semantic owner; +- first and latest applicable releases; +- evidence artifacts and checksums; +- reproduction command or procedure; +- what the evidence proves; +- what it does not prove; +- current status: passing, degraded, superseded, withdrawn; +- related failures, profiles, and architecture pages; and +- source-at-release links. + +No prose may convert an experimental, partial, or model-scoped result into a +general production guarantee. + +## Content governance + +| Content | Owner | Update trigger | +|---|---|---| +| SDK/runtime/CLI/reference facts | Generated release bundle | Public contract change | +| Security semantics | Rust semantic owner + security reviewer | Semantic identity change | +| Quickstart source/results | Scenario project | Fixture/package change | +| Operations procedures | Runtime/component owner | Configuration or behavior change | +| Integration ownership | Port/profile owner | Topology change | +| Product narrative | Documentation/product owner | Reviewed editorial change | +| Assurance claims | Evidence owner | Evidence or limitation change | + +## Editorial requirements supplied to P11 + +P11 must enforce the following requirements over the exact current-head docs +release. This epic defines their editorial meaning but does not implement a +parallel pipeline: + +1. release-bundle checksum and contract parsing; +2. public documentation coverage; +3. generated reference completeness; +4. all tested quickstarts and differential comparison; +5. HTML/Markdown semantic parity; +6. navigation, sitemap, search, and canonical links; +7. internal/external links; +8. accessibility, responsive, visual, and interaction tests; +9. Lighthouse performance budgets; +10. secret, privacy, unsupported-claim, and stale-version scans; +11. Pagefind/static search and agent discovery surfaces; +12. deployment manifest, preview smoke, atomic promotion, and rollback; and +13. unfamiliar-reader usability fixtures. + +## Editorial requirements for machine-readable surfaces + +- canonical `.md` for every public page; +- bounded section Markdown by stable section identity; +- `/llms.txt` and bounded `/llms-full.txt`; +- `/.well-known/auths-docs.json`; +- `/reference/manifest.json`; +- `/search-index.json`; +- `/sitemap.xml` and `/robots.txt`; and +- optional read-only documentation MCP after static surfaces qualify. + +P10 renders these surfaces from the verified page graph; this epic does not +author a separate Markdown or agent corpus. The documentation MCP, if enabled, +can search, read, resolve symbols, and explain stable errors. It cannot create +authority, accept credentials, execute effects, or access unpublished evidence. + +## Implementation steps + +- [ ] Curate the claims, evidence, limitations, and statuses exported by P3/P4 + into the assurance information architecture. +- [ ] Author the assurance landing and category-page narratives around P9's + generated claim components. +- [ ] Link product/security statements to exact claims. +- [ ] Declare content ownership and stable dependencies under Content Epic 0. +- [ ] Provide the editorial requirements above to P11's exact-head + qualification gate. +- [ ] Review P11 preview change summaries grouped by affected reader journey. +- [ ] Run structured usability tests for chooser, first quickstart, failure + handling, SDK lookup, and assurance reproduction. +- [ ] Check off all content epics only after their evidence appears in the + current release report. + +## Acceptance criteria + +- Every security claim resolves to current evidence and an explicit limitation. +- Withdrawing or superseding evidence automatically changes or blocks affected + public claims. +- Search, Markdown, agent discovery, and human HTML expose the same release and + stable identities. +- P11 proves that no required check passes against a stale source or docs head. +- P11 proves rollback restores HTML, Markdown, search, manifests, and downloads + together. +- Usability participants can select a path, complete a quickstart, diagnose a + failure, locate an SDK contract, and inspect evidence without facilitator + intervention. + +## Validation + +```text +npm ci +npm run test:content +npm run test:assurance +npm run test:a11y +npm run test:links +npm run test:markdown +npm run build +``` diff --git a/docs/specs/0040/content/epic_0.md b/docs/specs/0040/content/epic_0.md new file mode 100644 index 00000000..ab8dd26b --- /dev/null +++ b/docs/specs/0040/content/epic_0.md @@ -0,0 +1,203 @@ +# Content Epic 0 — Establish Platform and Editorial Ownership + +**Status:** Complete in `auths-docs` commit `4576625`. + +**Parent:** [AP-SPEC-040](../../0040-stripe-quality-documentation-platform.md) + +**Repositories:** `auths-proof` and `auths-docs` + +**Depends on:** AP-SPEC-040 Platform Epics 1 and 5 contracts; implementation +may begin against their checked fixture schemas. + +**Blocks:** Content Epics 1–9 and public content implementation in Platform +Epics 6, 9, 10, and 11. + +## Outcome + +Establish one enforceable boundary between generated product truth, tested +examples, and human-authored teaching before either workflow creates public +pages. Both lanes compile into one verified page graph and cannot silently +create competing signatures, endpoints, code samples, navigation, Markdown, +or assurance inventories. + +## Current problem + +AP-SPEC-040 originally combined documentation plumbing with representative +public content. The later content program added detailed editorial epics. That +created overlapping claims of ownership: + +- Platform Epic 6 and Content Epics 1–4 both described the product journey; +- Platform Epic 9 and Content Epics 6, 8, and 9 both described deep content; +- Platform Epics 10–11 and Content Epic 9 both described machine surfaces and + qualification; and +- route inventories could be interpreted as either generated structure or + manually authored navigation. + +Without an explicit compiler boundary, a product change could require edits in +source docs, generated reference templates, MDX prose, code fences, navigation, +Markdown renderers, and search metadata independently. + +## Three provenance classes + +Every public semantic block has exactly one provenance class: + +| Class | Owner | Examples | Editorial treatment | +|---|---|---|---| +| Generated fact | `auths-proof` release bundle | Signatures, routes, fields, errors, limits, profiles, versions, evidence status | Reference by stable identity | +| Tested scenario | Qualified scenario artifact | Rust, TypeScript, Python source, commands, normalized results, failure fixtures | Select scenario and display step | +| Editorial narrative | `auths-docs` MDX | Explanation, recommendation, conceptual diagram, transition, landing-card order | Author and review directly | + +If released behavior can make prose false, convert the disputed value into a +generated fact or scenario projection. Editorial prose may explain what a fact +means but cannot restate mutable values as its own source of truth. + +## Ownership matrix + +| Concern | Platform lane | Editorial lane | +|---|---:|---:| +| Stable operation, scenario, page, and section identities | Defines and validates | References | +| SDK signatures and docstrings | Extracts | Never copies | +| Runtime endpoints, profiles, errors, limits, evidence | Extracts | Explains through components | +| Executable code and expected output | Builds and qualifies | Selects and contextualizes | +| MDX schema and registered components | Implements | Uses | +| Reader journeys and recommended paths | Provides typed model | Chooses and authors | +| Landing-card selection and order | Validates identities | Owns | +| Architecture and lifecycle explanations | Provides fact-backed components | Owns prose and conceptual views | +| HTML, Markdown, search, navigation, and LLM rendering | Implements once | Supplies page models | +| Content requirements | Enforces declared policy | Defines editorial acceptance | +| CI orchestration, exact-head checks, release, rollback | Owns | Does not reimplement | + +## Composition contract + +```text +AuthsDocsReleaseBundleV1 AuthoredPageSourceV1 +facts + scenarios prose + stable references + \ / + \ / + v v + DocsPageCompiler + | + v + VerifiedPageGraphV1 + / | | \ + HTML Markdown Search Agent surfaces +``` + +The compiler parses both inputs into closed types and fails when: + +- an authored page references an unknown or incompatible identity; +- a mutable product fact appears in a manually authored fact slot; +- an executable example is not backed by a qualified scenario; +- two pages claim the same page or route identity; +- navigation references a route absent from the graph; +- HTML and Markdown select different semantic blocks; +- an assurance claim lacks current evidence or a limitation; or +- content uses a release fact from a different bundle identity. + +## Authored source contract + +Every authored page declares dependencies rather than copying facts: + +```yaml +id: auths.page.get-started.local/1 +uses: + operations: + - auths.operation.authority.execute/1 + scenarios: + - auths.scenario.rest-authorize/1 + profiles: + - auths.profile.application.rest-effect/1 + claims: + - auths.claim.exact-effect-commitment/1 +``` + +MDX embeds registered components such as: + +```mdx + + + +``` + +The content repository does not maintain parallel JSON files containing those +facts. It may keep bounded editorial configuration such as card order, +audience, reader depth, and related-page selection. + +## Change workflows + +### Product fact changes + +An installed API, endpoint, error, profile, limit, version, or evidence change +updates the immutable bundle. Generated reference and scenarios rebuild. The +dependency graph identifies affected editorial pages and requires review only +where the semantic dependency changed. + +### Editorial changes + +Prose, card ordering, recommendations, and conceptual diagrams rebuild only the +documentation repository. They cannot modify the selected product bundle or +generated facts. + +### Semantic changes + +The changed operation receives a new semantic identity or version. References +to the previous identity remain release-pinned or fail explicitly; the compiler +never rejoins pages by similar function names. + +### New public surfaces + +A new surface creates generated reference automatically. Closed discoverability +policy determines whether it also requires a catalog entry, landing-card +decision, tested scenario, or authored guide. + +## Repository and naming rules + +- Refer to platform epics as `P1`–`P11` and content epics as `C0`–`C9`. +- Keep product facts and immutable bundle construction in `auths-proof`. +- Keep public `.mdx`, editorial navigation configuration, and visual composition + in `auths-docs`. +- Do not add mutable `../auths-proof` dependencies to `auths-docs`. +- Use immutable local fixture bundles during development and immutable release + bundles in qualification. +- Build navigation, canonical Markdown, search, sitemap, and agent surfaces + from `VerifiedPageGraphV1`; none receives a separate source corpus. + +## Implementation steps + +- [ ] Add the two-lane execution map to `docs/specs/0040/README.md`. +- [ ] Freeze the three provenance classes in the page-model schema. +- [ ] Add stable dependency references to authored page frontmatter. +- [ ] Implement strict product-fact and scenario-reference components. +- [ ] Implement duplicate page, route, navigation, and fact ownership checks. +- [ ] Reject raw executable code fences on public pages unless a component + resolves them to a qualified scenario artifact. +- [ ] Reject manually authored generated-reference inventories and tables. +- [ ] Generate an affected-page report from semantic dependencies. +- [ ] Display block provenance and release identity in preview diagnostics. +- [ ] Update P6, P9, P10, P11, and C1–C9 to reference this ownership contract. +- [ ] Add CODEOWNERS or equivalent review routing for generated facts, + scenarios, editorial narrative, security claims, and operations procedures. + +## Acceptance criteria + +- Every public block can report one and only one provenance class. +- A changed SDK argument updates reference without editing MDX. +- A changed editorial paragraph does not rebuild or alter product artifacts. +- A copied signature, endpoint inventory, version table, or executable snippet + in editorial MDX fails qualification. +- One page graph produces HTML, Markdown, navigation, search, and agent output. +- The affected-page report is based on stable identities, not path or symbol + string similarity. +- Platform and content epics contain no conflicting ownership statements. + +## Validation + +```text +npm run test:content-ownership +npm run test:dependencies +npm run test:provenance +npm run test:examples +npm run test:markdown +npm run test:navigation +npm run build +``` diff --git a/docs/specs/0040/epic_1.md b/docs/specs/0040/epic_1.md new file mode 100644 index 00000000..b9ed1610 --- /dev/null +++ b/docs/specs/0040/epic_1.md @@ -0,0 +1,250 @@ +# Epic 1 — Freeze the Documentation Surface Contract + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Depends on:** AP-SPEC-034, AP-SPEC-038, `AGENTS.md`, +`architecture.toml`, `compliance.toml`, and +`docs/target-state/PROFILE_AND_DOMAIN_ABSTRACTION_BOUNDARY_PLAN.md` + +**Blocks:** Epics 2–11 + +## Outcome + +Create one versioned, machine-readable contract that identifies every public +Auths operation and its projections into Rust, TypeScript, Python, runtime +endpoints, profiles, errors, examples, and assurance evidence. + +This epic freezes identities and schemas. It does not build the website, +rewrite public prose, or generate reference pages. Its purpose is to prevent +the documentation system from joining surfaces by fragile function names, +URLs, source paths, or display labels. + +## Zero-context starting point + +Read these files completely before editing: + +- `AGENTS.md`; +- `docs/specs/0040-stripe-quality-documentation-platform.md`; +- `docs/specs/0034-auths-public-naming-consolidation.md`; +- `docs/target-state/PROFILE_AND_DOMAIN_ABSTRACTION_BOUNDARY_PLAN.md`; +- `bindings/public-topology-v1.json`; +- `bindings/typescript/api/public-api.txt`; +- `bindings/python/api/public-api.txt`; +- `release/semantic-freeze.json`; +- `release/release-subjects.toml`; +- `release/public-naming.toml`; +- `xtask/src/semantic_freeze.rs`; +- `xtask/src/sdk_experience.rs`; +- `xtask/src/sdk_vocabulary.rs`; and +- `xtask/src/main.rs`. + +Current facts: + +- Semantic freeze identifies the public Rust roots, their publishable closure, + and immutable release subjects. +- TypeScript and Python have installed-artifact public-name snapshots. +- `bindings/public-topology-v1.json` defines the supported product, vertical, + mechanism, extension, and test entry points. +- No stable identity currently joins one product operation to its SDK symbols, + runtime routes, guide dependencies, examples, errors, and evidence. +- The documentation repository must remain separate and must consume immutable + artifacts rather than a mutable sibling checkout. + +## Product constraint + +The contract must preserve one product vocabulary across all languages while +allowing idiomatic spelling in each language. A reader should see “create +authority” once and switch between `create_authority`, `createAuthority`, and +the Rust item without landing on three unrelated reference pages. + +The contract contains product facts, not marketing prose. It must be small, +deterministic, reviewable, and safe to publish. It must not contain secrets, +receipt bodies, arbitrary user data, credentials, tenant identifiers, or +mutable deployment state. + +## Architecture + +```text +semantic freeze + public topology + checked projection manifests + | + v + DocsContractInputV1 + | + strict parse/compile + | + v + DocsContractV1 + / | \ + v v v + canonical JSON SHA-256 ID bounded summary +``` + +Rust owns parsing, closed identities, canonical ordering, and validation. +`xtask` owns repository discovery, artifact existence checks, generation, and +drift detection. Website tooling must not become a dependency of a shipping +crate. + +## Identities and types + +Add bounded types equivalent to: + +```rust +pub struct DocsContractVersion(u16); +pub struct OperationId(BoundedSemanticId); +pub struct PageId(BoundedSemanticId); +pub struct ScenarioId(BoundedSemanticId); +pub struct SymbolPath(BoundedString); + +pub struct OperationDefinitionV1 { + id: OperationId, + status: DocumentationStatus, + product_verb: Option, + profiles: BoundedVec, + errors: BoundedVec, + scenarios: BoundedVec, +} + +pub struct SdkProjectionV1 { + operation: OperationId, + language: SdkLanguage, + package: PackageCoordinate, + entrypoint: PublicEntrypoint, + symbol: SymbolPath, + support: ProjectionSupport, +} +``` + +Required identity forms: + +```text +auths.operation.authority.create/1 +auths.page.start.rest-api/1 +auths.scenario.rest-authorize/1 +``` + +Identities are lowercase ASCII, dot-separated, explicitly versioned, and +bounded in length. Display names and URL slugs are separate fields. A renamed +symbol or page URL does not change the semantic identity. A changed operation +meaning requires a new identity version. + +`ProjectionSupport` is a closed enum: + +- `supported` with one exact public symbol; +- `not-supported` with one stable reason code; or +- `not-applicable` with one stable reason code. + +Absence is not a support state. + +## Contract files + +Add: + +- `release/docs/operations.toml`: semantic operation inventory; +- `release/docs/pages.toml`: stable generated and authored page identities; +- `release/docs/scenarios.toml`: scenario identities and required language + coverage; +- `release/docs/projections/rust.toml`; +- `release/docs/projections/typescript.toml`; +- `release/docs/projections/python.toml`; +- `product/spec/v1/auths-docs-contract.schema.json`; +- `release/auths-docs-contract-v1.json`: canonical generated snapshot; +- `xtask/src/docs_contract.rs`; and +- contract parsing types in the narrowest existing product/configuration crate + that can own them without introducing an inward dependency. Open an + architecture case file before creating a new crate. + +The TOML inputs are small mapping authorities. They do not duplicate function +signatures, arguments, return types, docstrings, endpoint paths, or error +descriptions. Later epics extract those facts from installed artifacts and +Rust-owned registries. + +## Command contract + +Add: + +```text +cargo xtask docs-contract +cargo xtask docs-contract --update +cargo xtask docs-contract --artifact-dir +``` + +The check command validates the checked-in snapshot and prints the exact update +command on drift. `--update` is the only write path. `--artifact-dir` may add +extracted surfaces in Epic 4 but must already be reserved in the command +parser. + +The canonical artifact includes: + +- schema and contract versions; +- source commit slot and semantic-freeze digest; +- stable operations, pages, scenarios, and projections; +- public package and entrypoint inventory; +- empty, typed slots for routes, profiles, errors, limits, evidence, symbols, + and provenance that later epics populate; and +- a digest over the canonical payload excluding its digest field. + +## Implementation steps + +- [ ] Define bounded identifiers and closed enums before parsing TOML. +- [ ] Reject unknown fields at every object and unknown enum values. +- [ ] Enforce global uniqueness for operation, page, and scenario identities. +- [ ] Enforce uniqueness of `(operation, language, package, entrypoint)`. +- [ ] Require one explicit projection state for every maintained language and + every operation in the launch surface. +- [ ] Resolve package and entrypoint names against + `bindings/public-topology-v1.json`. +- [ ] Resolve public Rust packages against semantic freeze. +- [ ] Verify that supported TypeScript and Python symbols appear in their + current public API snapshots, while treating those name snapshots as + temporary evidence rather than signature sources. +- [ ] Canonicalize maps and sets by semantic identity before encoding. +- [ ] Domain-separate the artifact digest with + `AUTHS-DOCS-CONTRACT\0\1`. +- [ ] Generate or exhaustively validate the JSON schema from the Rust types; + do not maintain two independent validators. +- [ ] Add the contract and schema to release subjects and semantic freeze. +- [ ] Add `docs-contract` to `cargo xtask ci` after the artifact is stable. + +## Adversarial tests + +Reject: + +- duplicate or differently cased identities; +- unversioned, empty, oversized, or non-ASCII identities; +- a display name or URL used as an identity; +- unknown packages or entrypoints; +- a supported projection without a symbol; +- a `not-supported` projection with a symbol; +- one symbol mapped to incompatible operation meanings; +- an operation with silent TypeScript or Python absence; +- malformed canonical ordering or a stale digest; +- unknown schema versions and fields; +- path traversal or absolute paths in provenance slots; and +- contracts that embed secret-like strings, URLs with credentials, receipt + bytes, or arbitrary examples. + +Property tests must prove deterministic parse/compile/encode behavior across +input ordering and that semantically different contracts produce different +canonical bytes in the generated corpus. + +## Validation commands + +```text +cargo test -p xtask docs_contract +cargo xtask docs-contract +cargo xtask semantic-freeze +cargo xtask arch +cargo xtask compliance +cargo xtask release-contract +``` + +Run the repository pre-commit configuration before committing. + +## Exit gate + +This epic is complete when a clean checkout produces one deterministic, +checksummed contract with stable operation/page/scenario identities, explicit +Rust/TypeScript/Python support states, release-subject coverage, and no copied +signatures or prose. An unfamiliar consumer can use only the schema and +artifact to understand how future extracted facts will join without knowing +the repository layout. diff --git a/docs/specs/0040/epic_10.md b/docs/specs/0040/epic_10.md new file mode 100644 index 00000000..84d5ce74 --- /dev/null +++ b/docs/specs/0040/epic_10.md @@ -0,0 +1,242 @@ +# Epic 10 — Deliver Machine-Readable and Agent-First Documentation + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs` + +**Depends on:** Epics 5–9 + +**Blocks:** Epic 11 + +## Outcome + +Make the same release-scoped documentation directly usable by browsers, +terminals, crawlers, coding agents, and later a read-only docs MCP server +without scraping site chrome or granting product authority. + +Machine surfaces are alternate renderings and indexes over the verified page +graph. They are not independently authored corpora. + +Content Epic 9 may define which editorial sections are useful to agents and +what context a reader needs, but this epic exclusively owns the rendering, +discovery formats, bounded output, and semantic parity mechanisms. Follow +[Content Epic 0](./content/epic_0.md); never accept a second Markdown or agent +content source. + +## Zero-context starting point + +Read: + +- parent sections 12, 13, 16, and 17; +- Epics 5, 7, 8, and 9; +- the verified page-graph and reference-manifest schemas; +- the HTML and Markdown component-rendering contracts; +- current Stripe agent/Markdown documentation patterns linked by the parent; + and +- Auths MCP product surfaces, ensuring the docs service remains a different, + inert boundary. + +## Static public contract + +Serve: + +```text +GET / canonical HTML +GET /.md canonical Markdown +GET //sections/
.md bounded canonical section Markdown +GET /llms.txt concise machine index +GET /llms-full.txt bounded essential corpus +GET /.well-known/auths-docs.json discovery and release metadata +GET /search-index.json bounded static search catalog +GET /reference/manifest.json release-scoped semantic identities +GET /sitemap.xml canonical human routes +``` + +Every response is immutable for a versioned release, has a bounded size, and +declares the release/contract identity through content and headers where the +host supports them. + +Section IDs are stable, closed page-model identities rather than heading-text +slugs inferred at click time. Only sections declared independently useful by +the page template receive a section Markdown route. + +## Canonical Markdown + +Render Markdown from `VerifiedPageGraph`, not by converting final HTML and not +from a second set of `.md` source files. + +Markdown must preserve: + +- title, description, release, status, and canonical URL; +- headings and prose; +- language-labelled executable examples; +- generated signatures and reference tables; +- security/failure/operations callout meaning; +- diagram text equivalents instead of inaccessible SVG alone; +- source/evidence links pinned to the release; and +- related semantic pages. + +Strip navigation chrome, theme controls, copy buttons, analytics, and hidden UI +labels. Component tests compare semantic blocks rather than whitespace. + +## Page actions + +Every public page offers: + +- **Copy for LLM** — copies canonical page Markdown only; +- **View as Markdown** — navigates to the `.md` URL; +- **Open source** — release-pinned authored source or generated provenance; +- **Report an issue** — pre-fills canonical page ID and release, not page + contents; and +- **Ask an agent** — copies a bounded prompt with canonical URL, release, + declared goal, and instruction to retrieve current page Markdown. + +Page actions appear immediately below the title and description. Long +reference templates also provide section actions beside eligible headings: + +- **Copy for LLM** copies only the canonical section Markdown; and +- **View as Markdown** opens `//sections/
.md`. + +A section projection includes its title, relevant prose, generated facts, +security/failure callouts, all declared language examples, page/section +identities, release, and parent canonical URL. It excludes adjacent sections, +navigation, inactive local UI state, and a sticky example belonging to another +semantic step. + +Copy actions never include cookies, local storage, search history, environment +values, account identifiers, credentials, or undisclosed receipt material. + +## Discovery formats + +`/.well-known/auths-docs.json` includes: + +- schema version; +- docs release and product release; +- contract and deploy digests; +- supported documentation versions; +- canonical base URLs; +- SDK coordinates and supported runtimes; +- Markdown URL convention; +- search, sitemap, and reference manifest URLs; and +- integrity/provenance metadata. + +`/reference/manifest.json` maps stable operation, page, symbol, endpoint, +profile, error, scenario, and evidence identities to release-specific URLs. + +`llms.txt` is a concise curated index. `llms-full.txt` contains the bounded +essential product/start/architecture corpus and links to deep reference rather +than concatenating every generated symbol page into an enormous payload. + +## Search contract + +Search runs over a bounded static index. It supports product vocabulary, +language symbols, error codes, endpoints, profiles, common synonyms, and page +titles. Results expose canonical URL, page ID, release, availability, language, +and a bounded excerpt. + +Do not index: + +- internal/private symbols; +- draft or excluded pages; +- raw receipt/proof/action material; +- source plans and scratch files; +- unpublished release bundles; or +- navigation/footer text. + +## Read-only docs MCP — phase two + +Add only after all static surfaces pass qualification: + +```text +search_auths_docs(query, version?, language?) +read_auths_doc(page_id, version?, section?) +resolve_auths_symbol(symbol, language, version?) +explain_auths_error(code, version?) +``` + +The server reads immutable static indexes and bounded Markdown excerpts. It: + +- has no product credentials, signer, custody port, runtime client, lifecycle + store, provider gateway, or mutation tool; +- cannot authorize, delegate, approve, execute, resume, disclose a private + receipt, or inspect caller state; +- rejects unknown versions/IDs and bounds query, excerpt, and result counts; +- returns canonical URLs and release identity with every result; and +- emits privacy-safe aggregate operations metrics only if explicitly enabled. + +Do not combine this server with Auths authority or agent-execution MCP tools. + +## Architecture + +```text +VerifiedPageGraph + | + +--> HTML renderer --------> /page + +--> Markdown renderer ----> /page.md + +--> index builders -------> llms / search / sitemap / manifest + | + +--> optional inert MCP ---> bounded reads of the same artifacts +``` + +All outputs record one page-graph digest. A parity checker ensures no output is +built from a different release or graph. + +## Implementation steps + +- [ ] Finish Markdown renderers for every allowed component. +- [ ] Generate and route canonical `.md` twins. +- [ ] Build page actions with bounded copy/prompt behavior. +- [ ] Generate eligible section Markdown projections and build reusable + section actions over stable section identities. +- [ ] Generate discovery metadata, reference manifest, sitemap, `llms.txt`, and + bounded `llms-full.txt`. +- [ ] Build the final static search index and synonym registry. +- [ ] Add semantic HTML/Markdown parity tests. +- [ ] Add content-type, cache, CSP, robots, and canonical-link behavior. +- [ ] Qualify all static surfaces before considering MCP. +- [ ] If MCP proceeds, implement it as a separate read-only deployment over + immutable artifacts and threat-model it independently. + +## Adversarial tests + +Catch: + +- HTML and Markdown with different outcomes or security warnings; +- Markdown generated by lossy HTML scraping; +- copied page content containing hidden UI or local state; +- a section copy containing neighboring content or the wrong sticky code rail; +- a section route derived from mutable heading text or an unknown section ID; +- a generated index pointing across releases silently; +- `llms-full.txt` exceeding its bound; +- draft/private pages appearing in search, sitemap, or manifests; +- a symbol resolver returning a similarly named private symbol; +- query or section parameters causing path traversal; +- an MCP result without release/canonical URL; +- MCP access to a runtime client, credentials, network destinations, or + mutation path; +- prompt injection stored in search metadata altering tool behavior; and +- receipts, actions, principals, credentials, or secrets leaking through logs + or indexes. + +## Validation commands + +```text +npm run docs:render-markdown +npm run docs:build-indexes +npm run test:markdown +npm run test:parity +npm run test:search +npm run test:machine-surfaces +npm run build +``` + +If phase-two MCP exists, add its contract, fuzz, bounded-input, and no-capability +tests as a separate required job. + +## Exit gate + +This epic is complete when every public page has equivalent HTML and Markdown, +machine indexes resolve stable identities for one exact release, page actions +and eligible section actions copy only bounded canonical projections, no private +material enters public indexes, and any docs MCP is demonstrably read-only, +effect-free, and isolated from all Auths product authority. diff --git a/docs/specs/0040/epic_11.md b/docs/specs/0040/epic_11.md new file mode 100644 index 00000000..22ae145e --- /dev/null +++ b/docs/specs/0040/epic_11.md @@ -0,0 +1,274 @@ +# Epic 11 — Enforce Cross-Repository Qualification and Release + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repositories:** `auths-proof` and `auths-proof-docs` + +**Depends on:** Epics 1–10 + +**Blocks:** Public documentation launch + +## Outcome + +Make documentation consistency a required property of the product change that +causes it. Public API, endpoint, profile, error, limit, fixture, evidence, or +source-documentation changes must automatically build the correct docs preview +from an immutable artifact and fail before merge when coverage drifts. + +Then qualify and deploy one exact pair of product and docs revisions with an +immutable rollback bundle. + +This epic owns CI orchestration, exact-head classification, release evidence, +deployment, and rollback. Content Epic 9 supplies editorial acceptance +requirements and claim-governance policy; it does not implement parallel CI, +deployment, Markdown, search, or release pipelines. Follow +[Content Epic 0](./content/epic_0.md). + +## Zero-context starting point + +Read: + +- the parent specification and all prior epics; +- `.github/workflows/` in both repositories; +- `xtask/ci-plan/`, `xtask/src/evolution_policy.rs`, `release.rs`, + `release_control.rs`, and `docs_contract.rs`; +- `release/release-subjects.toml` and release builder/promotion workflows; +- the docs repository build, test, and deployment scripts; +- GitHub required-check configuration documentation; and +- the intended Vercel/Cloudflare/object-storage deployment configuration. + +Do not reuse stale workflow runs or mutable branch artifacts. The repository +has already experienced stale-head and late semantic-drift failures; docs CI +must identify the current head and run early classification. + +## Pull-request architecture + +```text +auths-proof PR @ head SHA + | + v +build affected installed artifacts + | + v +docs contract fingerprint vs base + | + +-- unchanged --> record explicit no-change result + | + +-- changed ----> build immutable PR docs bundle + | + v + invoke docs workflow by pinned SHA + | + isolated auths-proof-docs checkout + | + contract + examples + reference + content + browser tests + | + v + immutable preview + result attestation + | + v + required check on the same auths-proof head SHA +``` + +The invocation passes bundle digest, artifact locator, source head/base SHAs, +docs workflow SHA, and expiration. It never passes a sibling path, mutable +branch as artifact identity, or unchecked URL. + +## Change classification + +Run the contract fingerprint and semantic diff immediately after the smallest +required public artifacts build. Automatically require docs qualification when +any of these change: + +- public Rust item/signature/docs; +- npm export/signature/TSDoc/package subpath; +- Python export/signature/docstring/module; +- operation/projection/page/scenario identity; +- runtime route, wire content, trust boundary, or limit; +- profile, stable error, lifecycle state, configuration, receipt, or evidence; +- executable fixture or normalized outcome; +- supported runtime/package/version policy; or +- public source provenance. + +There is no `docs-not-required` label. A code-path heuristic may skip expensive +artifact builds only when the contract classifier proves the public fingerprint +cannot change. + +## Docs workflow gates + +For a changed bundle, require: + +- bundle signature/checksum, provenance, schema, and source-head validation; +- exact locked toolchain and dependency installation; +- MDX/frontmatter/component policy; +- stable identity and projection completeness; +- installed-artifact/source-doc completeness; +- route/profile/error/limit/evidence completeness; +- executable Rust/TypeScript/Python scenario qualification; +- normalized semantic parity; +- reference and affected-page dependency generation; +- HTML/Markdown/search/manifest parity; +- internal, anchor, source, and stable-identity links; +- secret/sensitive-content scanning; +- HTML validation, browser behavior, and responsive layout; +- WCAG 2.2 AA automated checks and keyboard/no-JavaScript flows; +- deterministic critical-template screenshots; +- maintained desktop, tablet, narrow-mobile, and 200-percent-zoom screenshots + for home, guide, SDK reference, and runtime API reference templates; +- two-row header/search alignment, expanded/collapsed contextual navigation, + sticky-offset/anchor behavior, and dead-gutter checks; +- page-wide Rust/TypeScript/Python switching, Bash grammar override, JSON + result grammar, and page/section Markdown action checks; +- Lighthouse accessibility at least 95 and performance at least 90 under the + maintained profile; +- static production deployment smoke; and +- a bounded result attestation tied to both repository SHAs and bundle digest. + +External network links run nightly; canonical internal and pinned source links +remain PR gates. + +## Human review routing + +The contract diff separates: + +1. **Automatically regenerated facts** — signatures, parameters, routes, + errors, versions, profiles, limits, and manifests. +2. **Broken executable coverage** — must be fixed in the originating PR. +3. **Affected authored pages** — determined by declared semantic dependencies. +4. **Security-sensitive review** — trust, custody, receipts, disclosure, + provider-unknown, retry, and assurance changes require named owners. + +An affected page may be acknowledged as still correct only by an owner review +record tied to the exact contract diff. CI cannot auto-rewrite explanatory or +security prose. + +## Release architecture + +```text +qualified product release candidate + docs bundle + | + v +automation opens/updates docs release PR pinned by digest + | + v +full docs qualification + preview + usability sign-off + | + +--------+--------+ + v v +package promotion immutable docs bundle + | | + +--------+--------+ + v + docs.auths.dev stable +``` + +The deployment manifest records: + +- product release and commit; +- docs commit; +- docs-contract and bundle versions/digests; +- Rust/npm/Python package coordinates and digests; +- reference runtime image digest; +- build workflow identity; +- static output digest; +- deploy target and time; and +- prior deploy digest for rollback. + +Stable deployment must not precede package promotion to unavailable +coordinates. Package promotion must not advertise docs qualification that did +not pass for the same candidate. Use a staged release with one final promotion +decision rather than mutable post-release patching. + +## Deployment and rollback + +- Deploy only immutable static files. +- Use atomic alias/pointer promotion after smoke tests. +- Retain at least the supported-version bundles and the immediately prior + stable deployment. +- Rollback changes the serving pointer to an already-qualified bundle; it does + not rebuild old source. +- Preview URLs are unguessable or access-controlled before public release and + expire automatically. +- The site has no production database, credentials, or dependency on GitHub + availability after deployment. + +## Implementation steps + +- [ ] Add the early contract fingerprint and automatic change classifier to + `auths-proof` CI planning. +- [ ] Build and upload the immutable current-head PR docs bundle. +- [ ] Add a reusable, pinned `auths-proof-docs` qualification workflow. +- [ ] Validate head SHA before starting expensive work and again before + returning status. +- [ ] Publish a static preview and bounded change report. +- [ ] Add deterministic visual/interaction fixtures for the global shell, + navigation states, SDK/runtime reference layouts, and shared code components. +- [ ] Return one required check associated with the exact source head. +- [ ] Configure human review routing from semantic dependencies and code + ownership. +- [ ] Add nightly full-version, external-link, dependency, and example checks. +- [ ] Integrate docs qualification into release subjects and promotion. +- [ ] Build immutable deployment manifest, atomic promotion, and rollback. +- [ ] Run the Epic 6 unfamiliar-developer study against production-equivalent + preview. +- [ ] Exercise rollback and prove old pages, Markdown, search, and manifests + remain internally consistent. + +## Failure and adversarial tests + +Test: + +- stale candidate head before and after the docs build; +- a superseded workflow trying to set current-head success; +- changed public signature classified as internal; +- a label attempting to suppress required docs; +- artifact digest or source commit mismatch; +- mutable branch artifact substituted after invocation; +- docs workflow reference changed without review; +- package coordinate unavailable at preview or promotion; +- reference page generated from one release and example from another; +- an SDK reference preview labelled as a generic API reference; +- a header-height change leaving stale sidebar, code-rail, outline, or anchor + offsets; +- one language panel, Bash command, result block, or section Markdown action + disagreeing with the current verified page model; +- an icon-library root import passing despite breaching the client budget; +- a security-sensitive page auto-acknowledged without owner review; +- preview secret leakage or non-expiring preview; +- partial deploy and CDN cache inconsistency; +- GitHub outage after static deployment; +- rollback to an incomplete or mismatched bundle; +- flaky test quarantine without owner/issue/expiry; and +- current-head CI green while any required job remains queued or running. + +## Validation commands + +In `auths-proof`: + +```text +cargo xtask docs-contract +cargo xtask docs-bundle +cargo xtask ci +``` + +In `auths-proof-docs`: + +```text +npm ci +npm run qualify -- --bundle +npm run build +npm run deploy:smoke +npm run deploy:rollback-test +``` + +Exercise the cross-repository workflow from a real pull request before making +the check required. + +## Exit gate + +This epic is complete when a public product change cannot merge without a +current-head, digest-pinned docs preview; generated facts update automatically; +affected prose receives deliberate review; every launch gate and usability +target passes; `docs.auths.dev` serves one exact qualified release across HTML, +Markdown, search, examples, and reference; and rollback restores a previously +qualified immutable bundle without rebuilding it. diff --git a/docs/specs/0040/epic_2.md b/docs/specs/0040/epic_2.md new file mode 100644 index 00000000..0dfe731f --- /dev/null +++ b/docs/specs/0040/epic_2.md @@ -0,0 +1,238 @@ +# Epic 2 — Make the Public API Self-Documenting at Source + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Depends on:** Epic 1 + +**Blocks:** Epics 4, 7, 8, and 11 + +## Outcome + +Give every maintained public Rust, TypeScript, and Python symbol enough +source-owned documentation to generate an accurate reference without writing +reference prose in the website repository. + +This is foundational product work in `auths-proof`, not website copywriting. +The result must improve editor hover, `cargo doc`, TypeScript language-server +help, Python `help()`, and the generated site from the same source. Private +implementation is documented only where an invariant, trust boundary, or +non-obvious reason warrants it. + +## Zero-context starting point + +Read: + +- `AGENTS.md`; +- `docs/specs/0040-stripe-quality-documentation-platform.md`; +- `docs/specs/0040/epic_1.md`; +- `release/semantic-freeze.json` public Rust roots and publishable closure; +- `bindings/public-topology-v1.json`; +- `bindings/typescript/src/index.ts`, `product.ts`, `identity.ts`, `verify.ts`, + `profiles.ts`, `integrations.ts`, `framework.ts`, and `testkit/index.ts`; +- `bindings/typescript/tools/public-api.mjs` and + `bindings/typescript/api/public-api.txt`; +- `bindings/python/python/auths/__init__.py`, `__init__.pyi`, `identity.py`, + `verify.py`, `profiles/`, `integrations.py`, `framework.py`, and `testkit.py`; +- `bindings/python/tools/check_public_api.py`; +- the crate roots for `auths`, `auths-sdk`, `auths-runtime`, + `auths-production-client`, and every public Rust root; and +- `xtask/src/public_naming.rs`, `sdk_experience.rs`, and `sdk_vocabulary.rs`. + +Current facts: + +- The public API snapshots primarily freeze exported names, not documentation + completeness or reference-quality descriptions. +- Some Rust APIs have good `///` contracts and error sections, while the public + closure does not uniformly deny missing documentation. +- Many TypeScript public declarations have expressive types but no TSDoc. +- Python splits runtime facades, native types, and `.pyi` signatures; a docs + generator must merge these deliberately rather than treating one file as + the entire API. +- Auths values minimal, truthful comments. A blanket quota for private comments + would create noise and contradict that standard. + +## Documentation priority policy + +Apply these tiers in order: + +| Tier | Surface | Required treatment | +| --- | --- | --- | +| P0 | Five verbs, normal product constructors, outcome types, recovery, verification, runtime endpoints, maintained profiles, stable errors | Complete contract, trust boundary, failures, and executable example identity | +| P1 | Every symbol exported by a maintained Rust root, npm entrypoint, or Python module | Summary, semantic behavior, parameters/fields where meaning is not encoded by type, return/outcome behavior, and relevant errors | +| P2 | Public extension ports, adapter contracts, custody/transport/store interfaces, protocol types | P1 plus implementer invariants and what the port must not infer | +| P3 | Public members in the publishable Rust closure not directly re-exported by a root | Accurate summary and safety/error contract; deeper prose only where useful | +| P4 | Private code | No coverage target. Document only security invariants, protocol rationale, unsafe assumptions, or surprising constraints | + +P0 and P1 block the docs launch. P2 blocks publishing an extension surface. +P3 is enforced before its crate is independently marketed. P4 is never +measured by percentage. + +## Content standard + +Every P0/P1 symbol must have: + +1. one plain-language summary sentence; +2. when to use it, if the name and type do not make that obvious; +3. semantic meaning for parameters or fields that cannot be inferred safely; +4. the closed return or outcome behavior; +5. errors, denials, indeterminate states, recovery behavior, and retry class + where applicable; +6. a security or trust-boundary section when it accepts untrusted bytes, + identity evidence, authority, custody, provider state, transport data, or + disclosure material; and +7. a stable scenario identity for P0 executable examples. + +Documentation must not: + +- repeat a type signature in prose; +- promise behavior not fixed by tests or semantic identity; +- call an API “simple”, “safe”, “secure”, or “production-ready” without naming + the bounded property; +- expose internal workflow/spec commentary; +- use migration, deprecation, or compatibility language for unpublished + surfaces; +- paste credentials, private keys, receipt bodies, or realistic secrets; or +- explain private implementation where a public contract is sufficient. + +## Language ownership + +### Rust + +Rust `///` and `//!` documentation is canonical for Rust public semantics. +Publishable public crates enable `missing_docs = "deny"` once their tier is +complete. Fallible functions document `# Errors`; public panics document +`# Panics`; unsafe APIs document `# Safety`; security-sensitive APIs use a +`# Security` section. Examples reference repository scenario sources and use +`no_run` only when a real external service is required. + +Do not add `#[allow(missing_docs)]` to bypass a public surface. Generated code +may have one narrow, file-scoped allowance only when its generator emits the +corresponding reference metadata and CI tests it. + +### TypeScript + +TSDoc on exported declarations is canonical. Use standard `@remarks`, +`@param`, `@returns`, `@throws`, and `@example` tags plus exactly two configured +Auths tags: + +- `@security` for trust and secrecy boundaries; and +- `@scenario` for a stable executable scenario identity. + +API Extractor must preserve the comments in its `.api.json` model. Re-exports +inherit one canonical declaration comment; barrel files do not duplicate it. +Interfaces document fields only when their semantic meaning exceeds the type +and property name. + +### Python + +The public `.py` facade owns user-facing docstrings and runtime `help()` +behavior. `.pyi` files own signatures and types. Griffe merges the installed +runtime object with its stub; disagreement is a build failure. + +Use one consistent section form: `Args`, `Returns`, `Raises`, `Security`, and +`Examples`. Only relevant sections are present. Public native `_native` symbols +remain private implementation details where possible. A native class that is +directly re-exported must expose a real runtime `__doc__` from its PyO3 +definition and match its public stub identity. + +Do not copy full Python docstrings into `.pyi`. The stub may carry a one-line +type-only clarification when necessary, but the merged model must have one +canonical narrative source. + +## Architecture + +```text +Rust /// TypeScript TSDoc Python .py + .pyi + | | | + v v v +rustdoc model API Extractor model Griffe merged model + | | | + +--------------------+-------------------------+ + | + v + public-doc policy checker + | + summary / errors / security / + scenario / runtime visibility +``` + +## Tooling and files + +Add: + +- `docs/public-api-documentation-policy.toml`: tier assignments, required + sections, exemptions, owners, and expiry dates; +- `xtask/src/public_docs.rs`: Rust inventory and cross-language policy runner; +- `bindings/typescript/tools/public-docs.mjs`: TSDoc/API-model checker; +- `bindings/typescript/api/tsdoc.json`: exact custom tag configuration; +- `bindings/python/tools/check_public_docs.py`: installed runtime/stub/Griffe + documentation checker; and +- `release/docs/public-docs-report.json`: generated bounded coverage report. + +Prefer extending existing public API tooling rather than adding a parallel +export inventory. The generated report records counts and stable missing +symbol identities, not prose bodies. + +## Implementation steps + +- [ ] Inventory P0 operations from the Epic 1 contract. +- [ ] Map every maintained public symbol to P0–P3; default an unmapped public + symbol to failure rather than P4. +- [ ] Establish the content rules and narrow exemption format. Every exemption + requires an owner, reason, issue, and expiration date. +- [ ] Complete P0 Rust crate/module/item docs and enable missing-doc denial. +- [ ] Complete P0 TypeScript TSDoc and prove it survives declaration emission + and packing. +- [ ] Complete P0 Python runtime docstrings and prove installed wheel/stub + merging. +- [ ] Complete P1 across the public Rust roots and maintained SDK entrypoints. +- [ ] Complete P2 extension contracts before advertising adapter authoring. +- [ ] Add P3 enforcement incrementally across the publishable Rust closure; + finish the closure before the docs launch. +- [ ] Add documentation checks to existing Rust, npm, and wheel package jobs. +- [ ] Generate a privacy-safe report grouped by tier, language, package, and + owner. +- [ ] Run doctests and doc examples against deterministic fixtures or clean + installed consumers. + +## Adversarial tests + +The checks must catch: + +- a newly exported undocumented symbol; +- a documented barrel re-export whose canonical declaration is undocumented; +- TypeScript comments stripped from packed declarations; +- a Python name in `__all__` absent from its stub or runtime package; +- a Python stub signature paired with the wrong runtime object; +- a direct PyO3 public export with an empty runtime `__doc__`; +- `# Errors` or `Raises` text that omits a stable closed failure; +- a security-sensitive P0 operation without a security section; +- an example tag naming a nonexistent or incompatible scenario; +- a stale, expired, or overbroad exemption; +- secrets or realistic identifiers in documentation examples; and +- private-comment quantity being used to satisfy a public-doc requirement. + +Snapshot tests must normalize whitespace without discarding semantic sections. +Doc-only edits must not change protocol, ABI, wire, or runtime commitments. + +## Validation commands + +```text +cargo xtask public-docs +cargo doc --workspace --no-deps +cargo test --doc --workspace +cd bindings/typescript && npm run build && node tools/public-docs.mjs +cd bindings/python && python tools/check_public_docs.py +cargo xtask package +``` + +Run the repository pre-commit configuration before committing. + +## Exit gate + +This epic is complete when every P0/P1 symbol in installed Rust, npm, and wheel +artifacts has source-owned, reference-quality documentation; P2 extension +contracts describe their invariants; the public Rust closure has a bounded P3 +completion plan with no silent gaps; editor/runtime help exposes the same +meaning the docs extractor will consume; and no requirement rewards comments +on ordinary private implementation. diff --git a/docs/specs/0040/epic_3.md b/docs/specs/0040/epic_3.md new file mode 100644 index 00000000..102331d1 --- /dev/null +++ b/docs/specs/0040/epic_3.md @@ -0,0 +1,242 @@ +# Epic 3 — Export Runtime, Profile, Error, and Assurance Facts + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Depends on:** Epic 1 and AP-SPEC-038 + +**Blocks:** Epics 4, 8, 9, and 11 + +## Outcome + +Make the non-SDK product surface machine-readable from Rust-owned sources: +runtime routes, wire contracts, profiles, stable outcomes and errors, limits, +configuration, lifecycle states, receipt disclosure modes, and assurance +evidence. + +The result must eliminate manually maintained endpoint inventories and profile +tables without creating a generic router, generic provider executor, or second +authorization semantics layer. + +## Zero-context starting point + +Read: + +- `AGENTS.md`; +- `docs/specs/0040-stripe-quality-documentation-platform.md`; +- `docs/specs/0040/epic_1.md`; +- `docs/specs/0038/epic_1.md`, `epic_3.md`, `epic_4.md`, and `epic_5.md`; +- `product/runtime/auths-node/src/api.rs`, `config.rs`, and `profiles.rs`; +- `product/runtime/auths-production-client/src/lib.rs`; +- `product/runtime/auths-lifecycle/src/`; +- `product/errors/auths-errors/src/lib.rs`; +- `xtask/src/error_registry.rs`; +- `bindings/public-topology-v1.json`; +- `bounded-domains.toml`; +- `release/open-production-candidate.json`; +- `release/release-subjects.toml`; and +- `release/assurance/open-production-candidate-1/`. + +Current facts: + +- `auths-node` explicitly registers health, version, metrics, authority, + profile execution, workflow, and receipt routes in Axum. +- Public production requests use a bounded CBOR content type and one Rust-owned + product contract rather than arbitrary JSON APIs. +- Stable error, profile, lifecycle, production candidate, fixture, and + assurance inventories already exist, but they do not expose one joined docs + projection. +- Scraping Rust source text or maintaining a parallel website endpoint list + would drift. + +## Product constraint + +The reference must explain an endpoint as a product operation, not merely an +HTTP path. Each endpoint page must show: + +- what exact effect or inspection it represents; +- request and response content type and size limits; +- authorization, authentication, and transport boundaries; +- closed success, denial, indeterminate, recoverable, and unavailable + outcomes; +- stable errors and recommended actions; +- replay/idempotency/recovery behavior; +- profile and evidence identities; and +- an executable scenario when the endpoint can cause or resume an effect. + +Health and metrics endpoints are documented as operational surfaces and never +misrepresented as authorization operations. + +## Architecture + +Declare every public route once through a narrow registration macro or typed +builder that emits both the concrete Axum route and its metadata: + +```text +documented route declaration + | \ + v v +concrete Axum registration RuntimeEndpointSpecV1 + | | + v v +runtime behavior docs contract exporter +``` + +The mechanism may reduce registration duplication but must not abstract +profile handlers into `execute(profile, json)`. Each OpenTofu, PostgreSQL, and +GitHub handler remains a concrete function with concrete profile semantics. + +## APIs and types + +Add closed metadata types in `auths-node` or the nearest existing non-circular +contract crate: + +```rust +pub struct RuntimeEndpointSpecV1 { + id: EndpointId, + operation: OperationId, + page: PageId, + class: EndpointClass, + method: HttpMethod, + path: StaticEndpointPath, + content: EndpointContentContract, + outcomes: BoundedVec, + errors: BoundedVec, + profile: Option, + limits: EndpointLimits, + trust: EndpointTrustBoundary, + scenario: Option, +} +``` + +Closed endpoint classes: + +- `health`; +- `version`; +- `metrics`; +- `authority`; +- `profile-execution`; +- `workflow-recovery`; +- `workflow-inspection`; +- `receipt-summary`; and +- `receipt-disclosure`. + +The trust boundary records facts such as “TLS required by production client,” +“body remains untrusted until native parsing,” “transport success is not +authorization,” and “full receipt requires disclosure authorization.” It does +not contain free-form claims. + +Add a read-only exporter interface: + +```rust +pub trait DocumentationFacts { + fn docs_facts(&self) -> BoundedDocsFactsV1; +} +``` + +Prefer pure projections from existing typed registries. The trait cannot +mutate state, execute an operation, resolve secrets, call a provider, or mint +authority. + +## Sources and provenance + +Export: + +- route facts from the route declarations used to build `Router`; +- wire/content facts from `auths-production-client` constants and types; +- limits from compiled `AuthsConfig` and bounded protocol constants; +- profiles from the qualified profile registry and public topology; +- errors and recommended actions from `auths-errors` and its generated + registry; +- lifecycle states from the Rust lifecycle model; +- receipt disclosure modes from the Rust receipt inspection contract; +- release/runtime versions from release subjects; +- evidence identities and limitations from the assurance manifest; and +- exact source links from the release commit plus repository-relative owner + paths. + +Every exported fact includes a provenance kind and semantic subject. Do not +copy descriptive prose from README files into the facts artifact. + +## Files to add or change + +- `product/runtime/auths-node/src/api.rs`: single-source documented route + declarations. +- `product/runtime/auths-node/src/docs.rs`: endpoint metadata types and bounded + exporter. +- `product/runtime/auths-production-client`: wire/content contract projection. +- `product/runtime/auths-lifecycle`: lifecycle documentation projection only + if existing closed enums cannot be inspected without widening mutation. +- `product/errors/auths-errors`: stable read-only error projection. +- maintained profile registries: stable read-only profile projections. +- `xtask/src/docs_contract.rs`: join the exported facts into the Epic 1 + artifact. +- `product/spec/v1/auths-docs-contract.schema.json` and generated contract. +- semantic freeze and release subjects for intentional new facts. + +No website package or JavaScript runtime enters the Rust dependency graph. + +## Implementation steps + +- [ ] Define bounded paths, methods, classes, content types, limit fields, and + trust-boundary flags. +- [ ] Convert the existing route registration to one single-source declaration + mechanism without changing handlers, middleware order, paths, or responses. +- [ ] Add a compile-time or test-time uniqueness check for method/path, + endpoint identity, operation identity, and page identity. +- [ ] Require effectful and recovery endpoints to name a real scenario. +- [ ] Require every declared error to resolve in the stable error registry. +- [ ] Require every profile to resolve in public topology, production + candidate, and its fixture/evidence inventory. +- [ ] Export configuration defaults and limits only from compiled types. +- [ ] Export assurance claims and limitations only from the checked release + assurance manifest. +- [ ] Join all facts into the documentation contract with source provenance. +- [ ] Add an endpoint table to the bounded human contract summary. +- [ ] Prove generation has no network, provider, credential, or state-store + access. + +## Adversarial tests + +Reject or fail on: + +- a public route registered without metadata; +- metadata with no registered route; +- duplicate method/path with different meanings; +- an effectful endpoint classified as health or inspection; +- a route that names an unknown operation, page, profile, error, or scenario; +- request limits that disagree with runtime middleware; +- a receipt disclosure endpoint described as publicly readable; +- a provider-unknown outcome described as retryable success or failure; +- a route inventory obtained by scraping `api.rs` text; +- mutable state, credential access, or provider calls during export; +- arbitrary labels, secrets, database URLs, key IDs, or receipt bytes in the + artifact; and +- stale profile, error, evidence, or release-subject digests. + +Snapshot tests must prove the exporter remains deterministic across hash-map +ordering. Runtime integration tests must prove the route refactor produces the +same status codes, headers, body limits, timeouts, and handler outcomes. + +## Validation commands + +```text +cargo test -p auths-node +cargo test -p auths-production-client +cargo test -p auths-errors +cargo xtask error-registry +cargo xtask docs-contract +cargo xtask production-contract +cargo xtask semantic-freeze +cargo xtask arch +cargo xtask compliance +``` + +Run the repository pre-commit configuration before committing. + +## Exit gate + +This epic is complete when adding a public runtime route without its exact +contract is impossible, every route/profile/error/limit/evidence fact has one +Rust-owned source and provenance identity, the docs contract regenerates +deterministically, and the refactor leaves runtime behavior byte- and +outcome-equivalent. diff --git a/docs/specs/0040/epic_4.md b/docs/specs/0040/epic_4.md new file mode 100644 index 00000000..b2e2f871 --- /dev/null +++ b/docs/specs/0040/epic_4.md @@ -0,0 +1,227 @@ +# Epic 4 — Extract Installed SDK Surfaces and Publish the Docs Bundle + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Depends on:** Epics 1–3 + +**Blocks:** Epics 7–11 + +## Outcome + +Extract exact signatures and source-owned documentation from the Rust crates, +packed npm package, and built Python wheel that users actually install. Join +those surfaces with the stable operation contract and publish one immutable, +checksummed documentation bundle for `auths-proof-docs`. + +This epic is the automation waist. It must make an argument change, return-type +change, export change, or documentation change visible without hand-editing a +website reference page. + +## Zero-context starting point + +Read: + +- `AGENTS.md`; +- `docs/specs/0040-stripe-quality-documentation-platform.md`; +- Epics 1–3 in this folder; +- `bindings/typescript/tools/public-api.mjs`, `package.json`, and `tsconfig.json`; +- `bindings/python/tools/check_public_api.py`, `check_wheel.py`, + `pyproject.toml`, and `python/auths/_native.pyi`; +- `.github/workflows/typescript-sdk.yml` and `python-sdk.yml`; +- `xtask/src/package.rs` or the current packaging command implementation; +- `xtask/src/release.rs`, `release_control.rs`, and `docs_contract.rs`; +- `release/semantic-freeze.json`; and +- `release/release-subjects.toml`. + +Current facts: + +- TypeScript already inspects installed declaration exports and freezes their + names. +- Python already installs wheels in CI, verifies explicit `__all__`, typing, + and public-name snapshots. +- Rust semantic freeze identifies the public crate closure but does not expose + a normalized per-item documentation model. +- Stable Rust 1.97 rustdoc does not expose JSON output in its normal help; + structured Rust extraction therefore requires a separately pinned docs-only + nightly. That toolchain must not change the shipping MSRV or stable build. + +## Product constraint + +The docs show the artifact users install, not a favorable source-tree +approximation. If a comment, overload, class, function, type, or Python object +does not survive packaging, it is not public documentation. + +Cross-language pages join by operation identity. They may show idiomatic +language differences but must not imply parity where the capability contract +says unsupported. + +## Architecture + +```text +release candidate + | + +--> cargo package/crates --> pinned rustdoc JSON --> RustSurfaceV1 + | + +--> npm pack/install ------> API Extractor JSON -> TypeScriptSurfaceV1 + | + +--> wheel/install ---------> Griffe + inspect ---> PythonSurfaceV1 + | + +--> runtime/profile/error/evidence facts --------> ProductFactsV1 + | + v + operation/projection completeness join + | + v + AuthsDocsReleaseBundleV1 + contract + sources + fixtures + manifest + checksums + provenance +``` + +Every extractor parses into a language-specific closed type. Only verified +surfaces may enter the cross-language join. + +## Tool decisions + +### Rust + +- Pin one exact nightly date in `rust-toolchain.docs.toml`. +- Run rustdoc JSON only against packaged public crates with the release feature + set. +- Pin the matching `rustdoc-types` schema in a build-only extractor. +- Normalize item IDs to crate coordinate plus public path; discard compiler- + internal unstable IDs. +- Retain signatures, generics, bounds, fields, variants, impl relationships, + stability, source-owned docs, and source provenance. + +### TypeScript + +- Add `@microsoft/api-extractor` at an exact locked version. +- Extract from `.d.ts` files inside a clean installed tarball consumer. +- Retain package subpath, exported name, overloads, type parameters, members, + signatures, release tags, TSDoc, and declaration digest. +- Keep `public-api.txt` as the compact merge gate; the API model becomes the + reference source. + +### Python + +- Pin Griffe in the docs build environment. +- Install the wheel into a clean virtual environment with no repository root + on `sys.path`. +- Merge runtime exports/docstrings with `.pyi` signatures and types. +- Retain module, qualified name, call signature, overloads, members, + annotations, docstring sections, runtime availability, and wheel digest. +- Fail if an object resolves from the source checkout instead of the wheel. + +## Bundle contract + +Publish an archive equivalent to: + +```text +auths-docs-bundle--.tar.zst +├── manifest.json +├── auths-docs-contract-v1.json +├── surfaces/ +│ ├── rust.json +│ ├── typescript.json +│ └── python.json +├── fixtures/ +│ ├── scenarios.json +│ └── normalized-outcomes.json +└── provenance/ + ├── subjects.json + └── checksums.json +``` + +The manifest binds product commit, release identity, semantic-freeze digest, +toolchain identities, extractor versions, package digests, contract digest, +and every member checksum. The bundle contains no compiled executable, secret, +private source file, arbitrary build log, or unbounded repository archive. + +## Join and mapping rules + +- A supported SDK projection must resolve to exactly one installed public + symbol. +- A mapped symbol may represent multiple overloads but one product meaning. +- An installed maintained entrypoint symbol not classified as product, + extension, testkit, or explicitly internal fails. +- All P0/P1 symbols must carry the Epic 2 documentation sections. +- A signature fingerprint change preserves its operation identity only when + the meaning is unchanged; semantic change requires an operation version. +- A capability present in Rust and absent from TypeScript or Python requires an + explicit support state and reason. +- Source provenance uses the release commit and repository-relative path, not + mutable branch URLs or source line numbers as identity. + +## Files to add or change + +- `rust-toolchain.docs.toml`; +- `tools/docs-extractor/` or an existing build-tool location approved by + architecture policy; +- `bindings/typescript/api-extractor.json` and package dependencies; +- `bindings/typescript/tools/docs-surface.mjs`; +- `bindings/python/tools/docs_surface.py`; +- `xtask/src/docs_contract.rs` and a narrow `docs_bundle.rs` module; +- release builder workflow steps and subject declarations; +- bundle schemas under `product/spec/v1/`; and +- deterministic extractor fixtures under `release/fixtures/docs/`. + +## Implementation steps + +- [ ] Pin and checksum the docs-only Rust toolchain and schema parser. +- [ ] Build each extractor against a minimal fixture artifact first. +- [ ] Normalize paths, ordering, whitespace, default values, and language- + specific unstable IDs deterministically. +- [ ] Install the real release candidate artifacts into empty consumers. +- [ ] Extract source docs and signatures from installed artifacts. +- [ ] Join every projection through the Epic 1 operation identity. +- [ ] Join runtime/profile/error/evidence facts from Epic 3. +- [ ] Emit exact coverage and affected-operation reports. +- [ ] Build the bounded archive and verify every checksum after extraction. +- [ ] Add the bundle to release subjects and the reusable release builder. +- [ ] Add `cargo xtask docs-bundle ` and a check-only verification + command. + +## Adversarial tests + +Catch: + +- an npm tarball missing a source-declared export; +- a `.d.ts` comment stripped during build; +- a wheel importing from the checkout; +- a Python runtime/stub signature mismatch; +- a Rust item present in source but absent from the packaged feature set; +- a rustdoc schema/toolchain mismatch; +- two symbols mapped to one operation accidentally; +- one symbol mapped to two incompatible operations; +- an undocumented P0/P1 installed symbol; +- hidden drift caused only by map ordering, CRLF, or absolute runner paths; +- a changed signature with an unchanged fingerprint; +- archive path traversal, symlinks, duplicate members, or checksum mismatch; +- a secret-like value or private build path in any public artifact; and +- a bundle claiming a different commit or package digest. + +Run golden extractor fixtures on Linux, macOS, and Windows where the installed +package differs. Their normalized semantic output must match. + +## Validation commands + +```text +cargo xtask package +cargo xtask docs-contract +cargo xtask docs-bundle target/platform-artifacts +cargo xtask release-contract +cd bindings/typescript && npm run test:api +cd bindings/python && python tools/check_public_api.py +``` + +Also install and inspect the generated npm tarball and wheel from clean +temporary consumers. Run the repository pre-commit configuration before +committing. + +## Exit gate + +This epic is complete when one immutable bundle reconstructs exact installed +Rust, TypeScript, Python, runtime, profile, error, and evidence surfaces; every +supported projection joins by stable operation identity; toolchain and package +provenance are pinned; and changing a public argument or export changes the +bundle automatically without a website edit. diff --git a/docs/specs/0040/epic_5.md b/docs/specs/0040/epic_5.md new file mode 100644 index 00000000..9447545d --- /dev/null +++ b/docs/specs/0040/epic_5.md @@ -0,0 +1,277 @@ +# Epic 5 — Build the Static Docs Foundation and MDX Contract + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs` + +**Depends on:** Epic 4's fixture bundle schema. Implementation may use a +checked fixture bundle before the first release bundle exists. + +**Blocks:** Epics 6–11 + +## Outcome + +Create the separate static documentation application, constrained MDX content +system, Auths design system, navigation shell, version/language state, local +search foundation, and deterministic HTML/Markdown rendering architecture. + +This epic produces representative pages and components. It does not yet write +the complete quickstarts or generate the deep reference. + +It owns schemas and composition primitives, not public narrative. Content Epic +0 freezes the provenance and ownership rules; Content Epics 1–9 supply authored +page models through those rules. + +## Zero-context starting point + +Before editing `auths-proof-docs`, read from `auths-proof`: + +- `AGENTS.md`; +- `docs/specs/0040-stripe-quality-documentation-platform.md`; +- Epics 1–4 in `docs/specs/0040/`; +- `docs/target-state/PROFILE_AND_DOMAIN_ABSTRACTION_BOUNDARY_PLAN.md`; +- the fixture docs bundle schema and sample artifact; and +- `bindings/public-topology-v1.json`. + +Then read every existing file in `auths-proof-docs`. Preserve its independent +Git history and package boundary. Never add a mutable `../auths-proof` path +dependency. + +## Fixed toolchain + +Use: + +- Node 22; +- npm with a committed lockfile and deterministic `npm ci` installs; +- Vinext on Vite, React server components, and `@mdx-js/rollup`; +- strict TypeScript; +- strict typed page models and parse-at-the-boundary contract loaders; +- Shiki; +- the official checked Auths SVG and one pinned, tree-shakable icon family; +- Pagefind; +- pinned `remark`/`rehype` plugins; +- Mermaid rendered to SVG at build time; +- Playwright, `axe-core`, and Lighthouse CI; and +- immutable static deployment. + +Use small client components for language selection, search, navigation, and +copy actions; keep documentation content server-rendered. Do not add a database, +runtime CMS, hosted search, or authentication without a later measured +requirement. + +## Content model + +All human-authored public pages are `.mdx`. Plans and internal repository docs +remain ordinary `.md` outside the public content collection. + +MDX may use only globally registered components. Add a policy plugin that +rejects: + +- arbitrary imports and exports; +- inline scripts and event handlers; +- network or filesystem side effects; +- raw HTML outside a small audited allowlist; +- unregistered component names; +- copied signatures, hand-written endpoint inventories, package-version + tables, and executable example fences; and +- frontmatter values outside the closed content schema. + +Typed frontmatter: + +```ts +interface AuthsPageFrontmatter { + id: PageId; + title: BoundedTitle; + description: BoundedDescription; + audience: readonly Audience[]; + depth: "understand" | "start" | "build" | "operate" | "inspect" | "verify"; + status: "draft" | "preview" | "stable"; + languages: readonly SdkLanguage[]; + products: readonly ProductArea[]; + reviewers: readonly OwnershipArea[]; + uses: SemanticDependencies; +} +``` + +Unknown keys fail. `uses` contains operation, profile, error, and scenario +identities, not URLs. + +## Architecture + +```text +verified release/fixture bundle authored .mdx + | | + strict contract parse strict content parse + | | + +-------------+--------------+ + v + VerifiedPageGraph + / | \ + v v v + HTML canonical MD Pagefind/indexes + | + v + immutable static bundle +``` + +Only schema-parsed data enters page components. The HTML renderer and Markdown +renderer consume the same page graph, so `.md` output is not a second content +source. + +## UX shell + +```text ++----------------------------------------------------------------------------+ +| [Auths logo] Auths Docs Search docs... GitHub [↗] | +| Start SDK Concepts Architecture | +|----------------------------------------------------------------------------| +| Start | Protect one REST effect | On this page | +| Development | | Outcome | +| SDKs | Give one caller exact authority ... | Build | +| API | | Failure | +| Architecture| [Rust] [TypeScript] [Python] | Next | +| Operate | +--------------------------------------------+ | | +| Reference | | tested code | | | +| | +--------------------------------------------+ | | +|----------------------------------------------------------------------------| +| Copy for LLM | View Markdown | Open source | Ask an agent | ++----------------------------------------------------------------------------+ +``` + +The page remains readable without JavaScript. Language tabs render all panels +in HTML, with CSS/default selection and an enhanced persisted choice when +JavaScript is available. The URL may accept `?lang=python` for shareable +selection but canonical content does not fork by query. + +Promote the proven local prototype into the qualified product while preserving +these UX contracts: + +- a two-row global header with official Auths mark/title upper-left, functional + search centered, GitHub icon/external indicator upper-right, and `Start`, + `SDKs`, `Runtime API`, `Concepts`, `Architecture`, and `Operations` + lower-left, plus a bounded `More` menu for `Integrations` and `Assurance`; +- contextual navigation flush to the left viewport edge, collapsible on + desktop and a drawer on narrow screens; +- one CSS design token for header height, consumed by every sticky offset, + anchor margin, and viewport calculation; +- page actions immediately below title/description; +- a three-column reference shell with middle content and right code rail on + the same visual plane; and +- one icon language with individual imports and no Unicode stand-ins. + +The search control must open the Pagefind-backed interface with `Command + K` +and `Control + K`, correct dialog/focus behavior, and no header reflow. A +decorative search button does not satisfy this epic. + +## Components + +Implement typed components listed in the parent specification, beginning with: + +- `GlobalHeader`, `ContextNavigation`, `PageOutline`, and `ReferenceShell`; +- `OutcomeHero`; +- `LanguageGroup`; +- `CodeBlock` and `CodeBlockWithResult` with the parent section 8.2 prop + contract; +- `TestedExample` placeholder over fixture scenarios; +- `ReferenceLink` and `ReferenceSignature` placeholders; +- `FiveVerbFlow` and `FiveNounMap`; +- `OutcomeMatrix`; +- `TrustBoundary`; +- `Lifecycle`; +- `ReceiptView`; +- `SecurityCallout` and `FailurePath`; +- `Diagram` with text equivalent; +- `VersionBadge` and `AvailabilityBadge`; and +- `PageActions` and a section-scoped `SectionActions` foundation. + +Every component needs HTML, no-JavaScript, narrow-screen, and Markdown +behavior. Components may standardize presentation but cannot invent semantics. + +## Repository layout + +Create the exact foundation described in parent section 13.3, including: + +- `site/src/content/docs/` for public `.mdx`; +- `site/src/components/` and `site/src/layouts/`; +- `site/src/pages/reference/` for later generated templates; +- `site/public/images/auths_logo.svg` as the canonical copied brand mark; +- `schemas/` for contract, page graph, and scenario types; +- `tools/fetch-release/` with checksum verification; +- `tools/build-page-model/`; +- `tools/render-markdown/`; +- `examples/` placeholders by scenario and language; and +- browser, contract, and visual test directories. + +Generated output lives under ignored build directories and is never hand +edited or committed. + +## Implementation steps + +- [ ] Pin the toolchain and lock every dependency. +- [ ] Add the strict release-bundle parser and fixture bundle. +- [ ] Add the typed content collection and MDX policy. +- [ ] Build the page graph and stable page-ID resolver. +- [ ] Implement the responsive shell, navigation, outline, theme, typography, + status colors, version selector, language state, and footer actions. +- [ ] Wire the official SVG, single icon family, two-row header, real centered + search, edge-aligned contextual navigation, and shared header-offset token. +- [ ] Implement the shared syntax renderer, `CodeBlock`, and + `CodeBlockWithResult`, including Bash override and JSON-default result + grammar without duplicating toolbar/copy behavior. +- [ ] Implement representative content, generated-reference, error, and + operations page templates. +- [ ] Add Pagefind over final rendered content. +- [ ] Add deterministic Mermaid-to-SVG with accessible text alternatives. +- [ ] Add canonical Markdown renderer interfaces, even if full coverage lands + in Epic 10. +- [ ] Add CSP, security headers, and a no-third-party-script assertion. +- [ ] Establish bundle-size, accessibility, and performance budgets. + +## Adversarial and UX tests + +Test: + +- malformed and unknown bundle schema versions; +- checksum mismatch and archive traversal; +- unknown frontmatter and semantic dependencies; +- MDX import, script, raw HTML, and unregistered components; +- reference links that use URLs instead of stable identity; +- language preference unavailable on the next page; +- JavaScript disabled; +- keyboard-only navigation, search, tabs, and page actions; +- keyboard opening/closing of search, focus return, and no header reflow; +- stale numeric sticky offsets after the header height changes; +- contextual navigation collapse that leaves a dead gutter; +- whole-library icon imports or replacement of official icons with text glyphs; +- Bash commands highlighted as the selected SDK language; +- JSON results rendered as untyped plain text; +- 320-pixel layout and 200-percent zoom; +- reduced motion, high contrast, and screen-reader landmarks; +- a diagram without a text equivalent; +- Pagefind accidentally indexing navigation chrome or unpublished pages; and +- production output containing source plans, fixture secrets, or build paths. + +## Validation commands + +Define stable scripts equivalent to: + +```text +npm ci +npm run typecheck +npm run lint:content +npm run test:contract +npm run build +npm run test:browser +npm run test:a11y +npm run test:performance +``` + +## Exit gate + +This epic is complete when the separate repository builds a polished static +site from one verified fixture bundle and constrained MDX; HTML and Markdown +share one parsed model; stable language/version state works without hiding +content; the exact global/header/navigation/code component contracts above pass +desktop and narrow-screen qualification; representative pages meet +accessibility/performance budgets; and no page can execute arbitrary MDX code +or duplicate generated facts. diff --git a/docs/specs/0040/epic_6.md b/docs/specs/0040/epic_6.md new file mode 100644 index 00000000..e9feb8f8 --- /dev/null +++ b/docs/specs/0040/epic_6.md @@ -0,0 +1,211 @@ +# Epic 6 — Build Journey Composition Contracts + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs` + +**Depends on:** Epic 5 and Content Epic 0 + +**Blocks:** Epics 9–11 + +## Outcome + +Build the typed page models, journey composition primitives, dependency +resolution, and usability instrumentation required to deliver progressive +product teaching without embedding public copy or choosing the final +information architecture in platform code. + +Content Epics 1–4 own the routes, recommendations, explanations, and reader +journeys. Executable source and generated reference facts are supplied by +Epics 7 and 8. This epic owns only the composition machinery joining those +inputs into the verified page graph. + +## Ownership boundary + +Follow [Content Epic 0](./content/epic_0.md). This epic may define closed page +shapes, registered components, validation, and instrumentation. It must not: + +- author or approve public narrative; +- freeze global navigation labels or landing-card order; +- copy signatures, endpoints, errors, limits, evidence, or executable code; +- create a second route or navigation corpus; or +- render HTML, Markdown, search, or agent output from separate content trees. + +## Zero-context starting point + +Read: + +- the parent specification, especially sections 3–11; +- Epics 1–5 in this folder; +- `docs/specs/0040/README.md` and `content/epic_0.md`; +- `docs/plans/simplify/README.md` and its final five-verb target; +- `docs/target-state/` product-surface decisions; +- `docs/product/AUTHS_AUTHORITY_LAYER.md`; +- `bindings/typescript/README.md` and production integration guide; +- `bindings/python/README.md` and integration recipes; +- the Rust SDK README and open production reference demo README; and +- the fixture release bundle and page schema from Epic 5. + +Treat repository plans as research, not public truth. Resolve claims against +the release contract and installed artifacts. + +## Product model + +Use only these default verbs: + +```text +create -> delegate -> execute -> resume -> verify +``` + +Use only these default nouns: + +```text +actor -> authority -> action -> outcome -> receipt +``` + +Approvals, profiles, custody, trusted context, stores, lifecycle transitions, +commitments, disclosure, and provider reconciliation are progressive depth. +They appear when the reader's task requires them, not as prerequisites for +understanding the first example. + +## Journey composition contract + +Provide closed models for: + +- topic landings with editorially ordered card references; +- deterministic integration-chooser inputs and recommendations; +- outcome guides with prerequisites, steps, explanation, failure paths, and + deeper links; +- semantic tours with accessible diagrams and progressive depth; +- contextual navigation derived from page identities; and +- stable page and section actions over the verified graph. + +Content Epics 1–3 supply instances of these models. The model validates route, +page, operation, scenario, claim, and related-page identities but does not +choose the public taxonomy. + +## Page contract + +Every guide follows: + +1. **Outcome** — one sentence describing the working result. +2. **Before you begin** — only real prerequisites. +3. **Build** — numbered, executable steps with progress. +4. **What Auths proved** — plain-language authority and effect explanation. +5. **Failure paths** — closed outcomes and safe next actions. +6. **Take it further** — deeper pages, never duplicated essays. + +Each page declares semantic dependencies and contains no hand-authored +signature, parameter, endpoint, package-version, or support table. + +## Quickstart composition + +Provide a guide-step model that can bind prose to qualified scenario steps +without copying their code or results. It must support install, setup, action, +execution, inspection, replay, mutation, and cleanup step kinds while allowing +Content Epics 2 and 4 to select the actual journey. + +The component rejects raw commands or code as step data. Displayed source and +expected results resolve from Epic 7 scenario identities. + +## Follow-up composition + +Provide continuation links that can carry a scenario family and semantic +operation from one guide to another. Content may reuse actors and actions +without duplicating scenario data. Receipt components enforce opaque, summary, +and authorized-full disclosure modes supplied by generated facts. + +## UX behavior + +- Global and contextual navigation consume Content Epic 1's verified editorial + configuration; component code does not hard-code its labels or order. +- One selected SDK language persists across the entire journey. +- The recommended language defaults to TypeScript for web-oriented REST + readers but the initial selector makes Rust and Python equally visible. +- Switching language keeps the reader at the same semantic step. +- “Why?” callouts explain one concept without forcing a protocol detour. +- Security-critical warnings are inline and never hidden in accordions. +- Completed, denied, indeterminate, recoverable, verified, and rejected have + distinct words and accessible visual treatment. +- Provider-unknown always says “observe before retry.” +- Page Markdown actions sit beneath the title/description before the first + semantic section. Section actions appear only where a long page benefits + from an independently useful bounded projection. + +## Platform implementation steps + +- [ ] Implement typed landing, chooser, guide, tour, step, continuation, and + contextual-navigation models. +- [ ] Implement registered MDX components over those models. +- [ ] Resolve all product facts and executable displays through stable bundle + identities. +- [ ] Generate the affected-page dependency graph from frontmatter. +- [ ] Reject duplicate routes, dangling identities, raw executable examples, + and manually authored generated-fact slots. +- [ ] Add preview provenance labels for generated facts, tested scenarios, and + editorial narrative. +- [ ] Add reusable usability instrumentation without collecting participant + personal data. +- [ ] Qualify the models against bounded fixture pages supplied by Content + Epic 0; do not treat fixture prose as public content. + +## Usability instrumentation + +Provide privacy-safe tooling that lets the content lane run unfamiliar-reader +tests. Content Epic 2 owns recruiting and conducting the study; this epic owns +only the event schema and aggregate report format. + +Record: + +- time to identify the recommended start; +- time to first working effect; +- commands copied and edited; +- language switches; +- every hesitation longer than two minutes; +- every mistaken assumption about identity, transport, approval, execution, or + receipts; and +- whether the developer can explain the exact authority afterward. + +Do not record page bodies, code values, credentials, receipt contents, or +participant identity. Content Epic 2 defines the success threshold. + +## Adversarial content tests + +Fail review or CI when: + +- a quickstart references an untested snippet; +- a page restates a signature or fixed limit; +- a security warning exists only on a deep page; +- transport success is described as authorization; +- approval is described as reusable authority; +- denial and indeterminate are collapsed; +- provider-unknown recommends blind retry; +- a receipt summary exposes full details; +- the language switch changes semantic steps; +- an SDK guide or reference is labelled only “API reference”; +- platform code hard-codes the public navigation taxonomy instead of consuming + verified editorial configuration; +- contextual navigation collapse does not widen the reading surface; +- an unpublished feature is presented as stable; or +- a page links to `next` from stable without an explicit warning. + +## Validation commands + +```text +npm run lint:content +npm run test:dependencies +npm run test:examples +npm run build +npm run test:browser +npm run test:a11y +``` + +Archive the anonymized usability script, aggregate timings, observed problems, +and resulting issue links without participant personal data. + +## Exit gate + +This epic is complete when Content Epics 1–4 can express their landings, tours, +choosers, guides, continuations, and contextual navigation without duplicating +product facts or executable source; every input compiles into one verified page +graph; and preview diagnostics expose provenance and affected-page ownership. diff --git a/docs/specs/0040/epic_7.md b/docs/specs/0040/epic_7.md new file mode 100644 index 00000000..f1f3f9ab --- /dev/null +++ b/docs/specs/0040/epic_7.md @@ -0,0 +1,252 @@ +# Epic 7 — Build Executable Cross-Language Examples + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs`, consuming immutable `auths-proof` bundles + +**Depends on:** Epics 4–6 + +**Blocks:** Epics 8, 10, and 11 + +## Outcome + +Make every displayed Rust, TypeScript, and Python example originate from a real +source file that CI installs, compiles or executes, and compares against the +same Rust-owned fixtures and normalized outcomes. + +Language switching becomes a semantic view over one scenario, not three +unrelated snippets that happen to look similar. + +Content Epic 4 owns quickstart sequencing and explanation. This epic owns the +scenario artifacts, execution, comparison, provenance, and safe display +projection consumed by those pages. + +## Zero-context starting point + +Read: + +- parent sections 8, 11, 13, and 19; +- Epics 1, 4, 5, and 6; +- the docs release-bundle schema and scenario inventory; +- `bindings/public-topology-v1.json`; +- the Rust, TypeScript, and Python installed-consumer tests; +- `bindings/typescript/test/` and `bindings/python/external/`; +- `product/fixtures/v1/` and core cross-language fixtures; +- `demos/open-production-reference/`; and +- `xtask/src/product_waist.rs`, `sdk_experience.rs`, and fixture tooling. + +## Scenario contract + +Define a closed manifest: + +```yaml +id: auths.scenario.rest-authorize/1 +operation: auths.operation.authority.execute/1 +profile: auths.profile.application.rest-effect/1 +languages: [rust, typescript, python] +steps: [create, execute, verify] +fixtures: + action: rest-effect-v1 + authority: one-use-authority-v1 +expected: + first: completed + replay: denied.replay-detected + mutation: rejected.commitment-mismatch +display: + files: + rust: rust/rest-authorize/src/main.rs + typescript: typescript/rest-authorize/index.ts + python: python/rest-authorize/main.py +``` + +Parse into closed types. Bound step count, file count, output size, fixture +references, process duration, and normalized result size. Scenarios cannot +contain commands, environment-variable interpolation, arbitrary shell, or +network destinations. + +## Launch scenarios + +At minimum implement: + +- protect one REST effect; +- delegate narrower authority to an agent; +- verify a receipt summary; +- request authorized receipt disclosure; +- deny exact replay; +- reject changed action bytes; +- expire authority; +- refuse delegation widening; +- return indeterminate trusted-context evidence; and +- return provider-unknown with recovery/resume. + +Reuse one coherent fictional application where possible. Each scenario names +its exact operation/profile identities and expected closed outcomes. + +## Architecture + +```text +ScenarioV1 + Rust-owned fixtures + | + +-------+-------+ + | | | + v v v + clean clean clean + Cargo npm wheel + consumer consumer consumer + | | | + +-------+-------+ + | + v + normalized outcomes + | + exact differential join + | + TestedExample component + reads source files only +``` + +The runner never evaluates code from MDX. It executes only checked scenario +entries from bounded local paths. + +## Installed consumers + +- Rust examples depend on the packaged crate tarballs or a release registry + mirror, never a sibling path. +- TypeScript examples install the exact npm tarball into an empty directory + with a generated lockfile captured as test evidence. +- Python examples install the exact wheel into an empty virtual environment + and remove the repository root from import resolution. +- All consumers use deterministic public keys, fixtures, ports, and clocks + intended for examples. Secret scanners inspect source and captured output. + +Production-shaped scenarios may connect to the open reference container. They +must use an isolated ephemeral instance with bounded startup and teardown and +must not require a cloud account. + +## Normalized outcome model + +Compare product meaning, not language formatting: + +```ts +type NormalizedOutcome = + | { kind: "completed"; operation: OperationId; commitments: DigestSet } + | { kind: "denied"; code: StableErrorCode; retry: RetryClass } + | { kind: "indeterminate"; code: StableErrorCode; retry: RetryClass } + | { kind: "recoverable"; state: RecoveryState; retry: "resume" } + | { kind: "verified"; commitments: DigestSet } + | { kind: "rejected"; code: StableErrorCode }; +``` + +Do not compare random signatures, timestamps, receipt bytes, local paths, or +language-specific object strings. Do compare stable codes, effect state, retry +class, semantic commitments, member order, and required disclosure mode. + +## Display contract + +``: + +- resolves the scenario through the verified page graph; +- reads the exact executed file and declared display range; +- synchronizes Rust/TypeScript/Python tabs by semantic step; +- shows the package version and last qualification digest; +- provides copy-file and source-at-release actions; +- never displays fixture secrets or captured environment; and +- renders useful fenced code plus source links in canonical Markdown. + +The HTML renderer composes Epic 5's shared `CodeBlock` and +`CodeBlockWithResult` components. Each displayed source declares its SDK +language and whether the region is Bash. Bash installation/start commands +retain the selected SDK association but use Bash grammar. Displayed normalized +outcomes declare their result grammar and default to JSON. Switching the +page-wide language changes every applicable source region while preserving the +same semantic step and normalized result meaning. + +The result panel is sourced from the bounded normalized outcome artifact for +the exact scenario run. It is not hand-authored display JSON and cannot contain +raw signatures, timestamps, receipt bytes, local paths, environment values, or +other fields excluded by the normalizer. + +Use explicit source markers only to select meaningful regions from setup-heavy +files. Markers must be comments understood by the extractor and stripped from +display; they cannot contain prose that belongs in the guide. + +## Files to add + +In `auths-proof-docs`: + +- `examples/scenarios/*.yaml`; +- `examples/rust//`; +- `examples/typescript//`; +- `examples/python//`; +- `tools/run-scenarios/`; +- `tools/normalize-outcome/`; +- `site/src/components/TestedExample.astro`; +- scenario schemas and golden normalized results; and +- tests for source extraction and tab synchronization. + +In `auths-proof`, change only fixture/export support required by a scenario. +Do not add docs-site dependencies or duplicate examples in SDK READMEs. + +## Implementation steps + +- [ ] Freeze the scenario schema and stable IDs. +- [ ] Implement one REST scenario in all languages and qualify the runner. +- [ ] Add exact differential comparison and readable mismatch reports. +- [ ] Add the remaining launch scenarios incrementally. +- [ ] Build `TestedExample` over source files and scenario metadata. +- [ ] Render source/result through the shared code components and validate + language, Bash override, result grammar, copy payload, and global selection. +- [ ] Reject MDX code fences marked as executable. +- [ ] Add source-at-release URLs through provenance, not branch URLs. +- [ ] Cache immutable package downloads by digest without sharing mutable + installation directories between jobs. +- [ ] Bound output and redact before artifact upload. +- [ ] Add a matrix across supported Node, Python, browser/WASM, and stable Rust + versions where the example surface applies. + +## Adversarial tests + +Catch: + +- source displayed but never executed; +- a shell region highlighted as Rust, TypeScript, or Python because global + language incorrectly overrides `isBash`; +- a normalized JSON outcome rendered without JSON grammar or copied from MDX; +- one code group retaining a stale language after the page-wide switch; +- a scenario language missing while declared supported; +- code importing from a sibling checkout; +- the wrong npm tarball, wheel, crate, fixture, or reference image; +- replay accidentally completing; +- mutation producing the same commitment; +- provider-unknown mapped to denied or completed; +- recovery example calling execute again instead of resume; +- nondeterministic ordering hidden by the normalizer; +- random or sensitive fields compared or rendered; +- display markers escaping the declared source file; +- an example opening an undeclared network destination; +- output exceeding its bound or containing a secret-like value; and +- Windows path/newline differences changing semantic results. + +## Validation commands + +Define: + +```text +npm run examples:prepare -- --bundle +npm run examples:run +npm run examples:compare +npm run examples:render-check +npm run test:examples +``` + +The final job starts from empty Cargo/npm/Python consumer directories and +retains only bounded normalized evidence. + +## Exit gate + +This epic is complete when every launch scenario executes from installed +artifacts in Rust, TypeScript, and Python where supported; normalized meanings +match Rust-owned fixtures; displayed code and results use the shared typed +components and are the exact bounded run artifacts; the page-wide selector is +semantically synchronized; and a signature, import, semantic, packaging, +language, or outcome drift fails before the docs can render it. diff --git a/docs/specs/0040/epic_8.md b/docs/specs/0040/epic_8.md new file mode 100644 index 00000000..8ff0dad4 --- /dev/null +++ b/docs/specs/0040/epic_8.md @@ -0,0 +1,268 @@ +# Epic 8 — Generate the Deep Reference from Stable Identities + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs` + +**Depends on:** Epics 4, 5, and 7 + +**Blocks:** Epics 9–11 + +## Outcome + +Generate concept-oriented operation pages and exact Rust, TypeScript, Python, +runtime API, profile, error, configuration, limits, lifecycle, receipt, +protocol, and assurance reference from the verified release bundle. + +No generated reference page is hand-edited or committed. A changed function +argument or new endpoint updates the proper page through stable identities and +fails the originating change if required coverage is missing. + +Content Epic 5 owns developer landing curation and explanatory introductions. +This epic exclusively owns generated reference facts, templates, and contract +diffs. + +## Zero-context starting point + +Read: + +- parent sections 8, 9, 13–15, and 19–20; +- Epics 1–5 and 7; +- the release bundle schemas and one verified bundle; +- the Auths page frontmatter and page-graph schemas; +- generated-reference template tests from Epic 5; and +- installed surface models from Epic 4. + +Do not infer joins from similarly named functions. Inspect the operation and +projection identities first. + +## Reference hierarchy + +Generate: + +```text +/reference/ +├── operations/ +├── sdk/ +│ ├── rust/ +│ ├── typescript/ +│ └── python/ +├── runtime-api/ +├── profiles/ +├── errors/ +├── configuration/
+├── limits +├── lifecycle +├── receipts +├── protocol/ +└── assurance/ +``` + +The operation page is the primary cross-language reference. Language-specific +symbol URLs exist for search, direct linking, and language detail but point +back to the same operation meaning. + +Surface kind is closed and visible. `sdk-operation` pages describe installed +Rust, TypeScript, or Python symbols; `runtime-api-operation` pages describe +HTTP method/path and wire behavior. Generated titles, breadcrumbs, navigation, +search records, Markdown metadata, canonical URLs, and install panels derive +from that kind. An SDK page cannot inherit the generic label “API reference,” +and a runtime API page cannot present an SDK function signature as its primary +contract. + +## Page model + +Parse release facts into a closed model equivalent to: + +```ts +interface ReferencePageModel { + pageId: PageId; + operation?: OperationId; + release: ReleaseIdentity; + title: string; + summary: SourceOwnedDocumentation; + projections: readonly SdkSymbolProjection[]; + endpoints: readonly EndpointProjection[]; + profiles: readonly ProfileProjection[]; + outcomes: readonly OutcomeProjection[]; + errors: readonly ErrorProjection[]; + scenarios: readonly ScenarioProjection[]; + trust: readonly TrustBoundaryFact[]; + provenance: readonly ProvenanceLink[]; + authoredLinks: readonly PageId[]; +} +``` + +All fields are bounded and schema-parsed. Rendering templates accept only the +verified model, never raw contract JSON. + +## Operation page UX + +```text +Create authority Stable · 1.0 +Create exact, bounded authority for one actor and action. + +[Rust] [TypeScript] [Python] ++---------------------------------------------------------------+ +| createAuthority(input: CreateAuthorityInput): AuthorityResult | ++---------------------------------------------------------------+ + +Parameters Outcomes Related +actor ... completed ... REST guide +action ... denied ... Delegation + +Security boundary +Untrusted action bytes are parsed and committed before authority exists. + +Examples · Errors · Runtime endpoint · Source at release +``` + +Parameter/member sections come from the installed declaration model. Product +meaning and trust facts come from source docs and Rust-owned facts. Templates +must make provenance visible without overwhelming the default view. + +The desktop template uses left contextual navigation, middle semantic content, +and a right language-aware code rail. The middle and right regions share the +same background plane with no heavy vertical divider. Each source or +source-plus-result unit is bounded by the shared dark code component. The rail +may remain sticky within the active semantic section, but its offset consumes +the global header-height token. Section-level Copy/View Markdown actions render +beside the section heading and resolve only that section's verified projection. + +## Automatic change mapping + +### Changed SDK argument + +1. Epic 4 extracts the new installed signature under the same operation ID. +2. The signature fingerprint changes. +3. The operation page model receives the new parameter automatically. +4. Epic 7 examples compile and identify broken call sites. +5. The page dependency graph lists authored pages using that operation. +6. The preview shows generated reference changes and required prose reviews. +7. Merge fails on an unmapped parameter, broken example, missing source docs, + incompatible version classification, or unresolved page review. + +There is no parameter table to update in MDX. + +### New runtime endpoint + +1. Epic 3 requires a route descriptor at registration. +2. The descriptor enters the release bundle with operation/page identities. +3. The endpoint template creates HTML, Markdown, navigation, search, and + manifest entries. +4. An effectful endpoint without outcome/error/trust/limit/scenario coverage + fails the bundle and never reaches deployment. + +### Renamed or removed surface + +Stale projections, scenario calls, `ReferenceLink` components, frontmatter +dependencies, and search aliases fail. Before public launch, cut over directly +without compatibility aliases. After 1.0, the older release contract continues +to render under its versioned path. + +## Search and linking + +Build one stable resolver: + +```ts +resolvePage(pageId, release): CanonicalUrl +resolveOperation(operationId, release, language?): CanonicalUrl +resolveSymbol(language, packageName, symbol, release): CanonicalUrl +resolveError(code, release): CanonicalUrl +``` + +Authored MDX uses `ReferenceLink`, `ReferenceSignature`, and semantic +frontmatter dependencies. It cannot hardcode generated reference paths. + +Search records include title, operation identity, SDK spellings, endpoint, +profile, error codes, product synonyms, language, release, availability, and +bounded excerpt. Do not index private types, internal source names, draft +pages, or unsupported claims. + +## Template implementation + +Create shared templates for: + +- operation and SDK symbol pages; +- runtime endpoints; +- profiles and exact effects; +- stable errors and recommended action; +- configuration and limits; +- lifecycle states and transitions; +- receipts and disclosure; +- protocol/wire subjects; and +- assurance claims, evidence, and limitations. + +Templates render HTML and canonical Markdown from the same model. Do not emit +MDX files and then parse them back. + +## Implementation steps + +- [ ] Implement strict bundle-to-page-model parsing. +- [ ] Build the stable page and operation resolvers. +- [ ] Join language projections, endpoints, profiles, errors, scenarios, and + evidence by semantic identity. +- [ ] Implement each reference template and Markdown projection. +- [ ] Implement distinct SDK/runtime-API surface templates and reject generic + or conflicting reference labels. +- [ ] Build the three-column reference shell, sticky code rail, global language + synchronization, and section-scoped actions over the verified page model. +- [ ] Generate navigation, search records, sitemap members, and reference + manifest from the page graph. +- [ ] Add authored-guide backlinks from declared semantic dependencies. +- [ ] Add contract-diff output grouped into automatic fact changes, broken + coverage, and human review required. +- [ ] Add source-at-release links from provenance. +- [ ] Bound reference page size and split oversized type/member trees without + changing identity. +- [ ] Verify a fresh build leaves the Git worktree clean. + +## Adversarial tests + +Reject: + +- a join by display name, slug, or function spelling; +- missing, duplicate, or conflicting operation projections; +- an undocumented argument or field in a P0/P1 symbol; +- a reference template inventing a default, limit, error, or security claim; +- an endpoint missing from navigation or Markdown; +- an unsupported language displayed as supported; +- an SDK operation labelled as a runtime API or a runtime endpoint labelled as + an SDK/API client function; +- a sticky code rail using a copied numeric header offset; +- a page-wide language change leaving one code/result panel stale; +- a section Markdown action including a neighboring operation or code step; +- a stale `ReferenceLink` or semantic dependency; +- a source link to a mutable branch; +- private/internal symbols in search; +- unsafe full receipt material in a default reference example; +- an assurance claim without evidence and limitations; +- a page whose HTML and Markdown represent different outcomes; and +- generated output becoming a checked-in or extractor input. + +Golden tests must cover one operation with all languages, one language-specific +operation, one endpoint, one profile, one error, one unsupported projection, +and one versioned removal. + +## Validation commands + +```text +npm run reference:build -- --bundle +npm run reference:check +npm run test:contract +npm run test:reference +npm run test:search +npm run test:markdown +npm run build +git diff --exit-code +``` + +## Exit gate + +This epic is complete when every supported public operation, symbol, endpoint, +profile, error, limit, lifecycle state, receipt form, protocol subject, and +assurance claim is discoverable through one exact release; unsupported states +and SDK/runtime-API surface kinds are explicit; the qualified reference shell, +code rail, and section actions consume the same verified page model; +HTML/Markdown/search agree; and an SDK argument or endpoint change reaches the +correct page without human routing or copied reference content. diff --git a/docs/specs/0040/epic_9.md b/docs/specs/0040/epic_9.md new file mode 100644 index 00000000..fb3b0e12 --- /dev/null +++ b/docs/specs/0040/epic_9.md @@ -0,0 +1,259 @@ +# Epic 9 — Build Deep-Content Composition Contracts + +**Parent:** [AP-SPEC-040](../0040-stripe-quality-documentation-platform.md) + +**Repository:** `auths-proof-docs` + +**Depends on:** Epics 3, 5, 6, and 8 and Content Epic 0 + +**Blocks:** Epics 10–11 + +## Outcome + +Build the fact-backed page models, components, validators, and dependency +contracts required for architecture, operations, integrations, and assurance. +Content Epics 6, 8, and 9 own the routes, prose, recommendations, and conceptual +diagrams published through those contracts. + +This epic makes deep editorial content safe to author without copying product +facts, runbook commands, configuration, integration inventories, or assurance +status into a second source of truth. + +## Ownership boundary + +Follow [Content Epic 0](./content/epic_0.md). This epic owns composition +machinery and generated projections. It does not own public narrative, page +selection, route taxonomy, integration recommendations, or assurance claim +interpretation. + +## Zero-context starting point + +Read: + +- parent sections 5–10 and 16; +- Epics 3, 5, 6, and 8; +- `docs/specs/0040/README.md` and `content/epic_0.md`; +- `AGENTS.md` and the profile/domain abstraction boundary plan; +- `docs/product/AUTHS_AUTHORITY_LAYER.md`; +- `docs/target-state/`; +- `docs/research/competition/`; +- `docs/integrations/`; +- AP-SPEC-038 and all `docs/specs/0038/epic_*.md`; +- AP-SPEC-039 to identify enterprise-only material; +- `release/assurance/open-production-candidate-1/`; +- `release/RELEASE_CONTROL.md` and `RELEASE_RUNBOOK.md`; +- open production, incident response, PostgreSQL, OpenTofu, and relevant field + lab demo documentation; and +- the verified docs bundle's profile, lifecycle, error, and evidence facts. + +Repository plans and demo claims are leads, not public facts. Reconcile every +claim with the selected release artifact. + +## Supported editorial shapes + +Support the following page families without hard-coding their final route +inventory: + +```text +/architecture/ +├── system-map +├── trust-boundaries +├── identity-authority-transport +├── exact-effect-profiles +├── lifecycle-and-recovery +├── custody-and-signing +├── stores-and-replay +├── outcomes-and-receipts +└── threat-model + +/operate/ +├── open-reference +├── configuration-and-doctor +├── postgresql +├── kms-and-pkcs11 +├── observability +├── backup-and-restore +├── recovery-and-reconciliation +├── upgrades-and-rollback +└── incident-response + +/integrations/ +├── oauth-oidc +├── spiffe +├── policy-engines +├── rebac +├── cloud-iam +├── ucan-biscuit +└── http-message-signatures + +/assurance/ +├── claims-and-limitations +├── conformance-and-fixtures +├── differential-evidence +├── formal-evidence +├── release-provenance +└── independent-review +``` + +The tree is an initial fixture for validating the models. Content Epics 6, 8, +and 9 own the final public inventory and ordering. Enterprise fleet +coordination, centralized multi-tenant operations, paid governance, and hosted +control-plane features remain separately classified and cannot become an +open-core prerequisite. + +## Architecture teaching contract + +Every architecture page distinguishes: + +- identity evidence from authority; +- authority from approval; +- approval from execution authorization; +- transport delivery from verification; +- pure decision from durable lifecycle state; +- durable reservation from provider effect; +- definite non-effect from unknown effect; +- receipt commitment from authorized disclosure; and +- protocol guarantees from profile/application/provider guarantees. + +Use horizontal diagrams with text equivalents. Diagrams are conceptual views +over typed release facts, not replacements for them. + +Example system map: + +```text +identity evidence -> create/delegate authority -> native verification + | + v + durable reservation + | + v + closed profile gateway + | + +---------+---------+ + v v + definite outcome outcome unknown + | | + v v + receipt observe + resume +``` + +## Operations contract + +Every operations procedure includes: + +1. supported topology and prerequisites; +2. exact configuration fields generated from the selected release; +3. secret slots without values; +4. readiness and safe diagnostic commands; +5. expected healthy output; +6. failure categories and effect-aware actions; +7. rollback/recovery behavior; +8. privacy and telemetry boundaries; and +9. evidence that qualified the procedure. + +Copyable commands use placeholders that cannot resemble working credentials. +Commands must be tested against an isolated reference deployment. Do not +publish internal endpoints, customer identifiers, or provider resource IDs. + +## Integration contract + +Integration guides are “Auths with,” not manufactured-versus comparisons. Each +guide states: + +- what the adjacent system supplies; +- what Auths supplies; +- where meaning is translated; +- which party owns identity, policy, state, custody, transport, effect, and + receipts; +- what cannot be inferred from the adjacent token/decision/identity; +- replay and lifecycle responsibilities; +- failure and unknown-effect behavior; and +- one executable or conformance-backed example. + +Use the evidence-based competitive research and primary specifications. Link +to the relevant external specification near claims. Do not imply another +project lacks a property that its current primary documentation supplies. + +## Assurance contract + +Generated assurance panels show only claims present in the release bundle, +their exact evidence subjects, qualification status, limitations, source +commit, and verification instructions. + +Authored prose may explain why evidence matters but cannot upgrade +“qualification evidence” to proof of universal correctness, production +availability, compliance, certification, or external audit. + +## Components and data + +Use: + +- `TrustBoundary` for ownership and untrusted inputs; +- `Lifecycle` for transition/effect/recovery state; +- `OutcomeMatrix` for closed result behavior; +- `ReceiptView` for disclosure levels; +- `ProfileContract` for exact-effect boundaries; +- `OperationalCallout` for effect-aware action; +- `Diagram` with accessible text; and +- generated `VersionBadge`, `ReferenceLink`, and evidence panels. + +Authored MDX declares semantic dependencies. Generated configuration, limits, +profiles, errors, and assurance facts are embedded by identity. + +## Platform implementation steps + +- [ ] Implement typed architecture, operations, integration, and assurance page + models. +- [ ] Implement `TrustBoundary`, `Lifecycle`, `OutcomeMatrix`, `ReceiptView`, + `ProfileContract`, `OperationalCallout`, and generated evidence components. +- [ ] Resolve configuration, commands, profiles, errors, limits, evidence, and + scenario output exclusively from immutable bundle identities. +- [ ] Validate accessible diagram text and trust-boundary semantics without + owning the editorial diagram itself. +- [ ] Validate integration ownership matrices and primary-source citations. +- [ ] Validate runbook preconditions, stop conditions, recovery, and tested + command identities. +- [ ] Validate assurance claims against current evidence and limitations. +- [ ] Provide Content Epics 6, 8, and 9 with preview fixtures and provenance + diagnostics. +- [ ] Reject open-core pages that depend on enterprise-only components. + +## Adversarial review + +Reject: + +- a diagram that shows transport or approval creating authority; +- a lifecycle diagram that turns provider-unknown into failure or retry; +- a runbook copying a secret or realistic provider identifier; +- configuration prose disagreeing with generated defaults; +- an integration guide that treats an OAuth scope, SPIFFE identity, policy + decision, IAM credential, UCAN, or Biscuit as interchangeable with Auths; +- an assurance claim without limitation or release subject; +- a demo result presented as broad production evidence; +- formal evidence described as covering code outside its model; +- enterprise coordination described as required for self-hosting; +- a command not executed against the selected release; and +- a security-critical action hidden behind progressive disclosure. + +## Validation commands + +```text +npm run lint:content +npm run test:dependencies +npm run test:runbooks +npm run test:links +npm run test:diagrams +npm run test:markdown +npm run build +npm run test:a11y +``` + +External links are checked nightly to avoid flaky pull-request failures, while +primary-specification URL syntax and internal links remain PR gates. + +## Exit gate + +This epic is complete when Content Epics 6, 8, and 9 can author their material +using typed, fact-backed components; runbook commands and assurance facts cannot +drift from the selected release; and every deep page compiles into the same +verified page graph used by the rest of the site. diff --git a/product/runtime/auths-runtime/src/docs.rs b/product/runtime/auths-runtime/src/docs.rs new file mode 100644 index 00000000..478c57a2 --- /dev/null +++ b/product/runtime/auths-runtime/src/docs.rs @@ -0,0 +1,235 @@ +//! Read-only facts for documentation and release tooling. + +/// Stable metadata for one production runtime endpoint. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct RuntimeEndpointSpecV1 { + /// Stable endpoint identity. + pub id: &'static str, + /// Product operation served by this endpoint. + pub operation: Option<&'static str>, + /// Stable documentation page identity. + pub page: &'static str, + /// Closed endpoint class. + pub class: EndpointClass, + /// HTTP method. + pub method: HttpMethod, + /// Absolute, template-form route path. + pub path: &'static str, + /// Maximum accepted request body in bytes. + pub max_body_bytes: u32, + /// Outcomes this endpoint may return. + pub outcomes: &'static [OutcomeKind], + /// Scenario that qualifies effectful or recovery behavior. + pub scenario: Option<&'static str>, + /// Trust-boundary facts fixed by the runtime contract. + pub trust: EndpointTrustBoundary, +} + +/// Closed classes used to organize the runtime API. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum EndpointClass { + /// Liveness without authority or provider access. + Health, + /// Runtime version and compatibility facts. + Version, + /// Authority creation and inspection. + Authority, + /// Authorization followed by closed profile execution. + ProfileExecution, + /// Recovery of a prior execution. + WorkflowRecovery, + /// Bounded receipt projection. + ReceiptSummary, + /// Authorized receipt disclosure. + ReceiptDisclosure, +} + +/// HTTP methods admitted by the V1 runtime contract. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum HttpMethod { + /// Read a bounded projection. + Get, + /// Submit exact bytes for parsing and processing. + Post, +} + +/// Closed outcomes exposed by runtime endpoints. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum OutcomeKind { + /// Operation completed and may carry a receipt. + Completed, + /// Authorization denied the requested effect. + Denied, + /// The runtime could not make a safe decision. + Indeterminate, + /// The provider result requires explicit recovery. + Recoverable, + /// Requested resource does not exist. + NotFound, +} + +/// Security facts for an endpoint, represented as closed booleans. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct EndpointTrustBoundary { + /// Maintained production clients require an HTTPS origin. + pub production_tls_required: bool, + /// Request bytes remain untrusted until native parsing succeeds. + pub native_parse_required: bool, + /// Successful transport cannot authorize an effect. + pub transport_is_not_authority: bool, + /// Full receipt material requires an authorized disclosure. + pub disclosure_required: bool, +} + +const READ_ONLY: EndpointTrustBoundary = EndpointTrustBoundary { + production_tls_required: true, + native_parse_required: false, + transport_is_not_authority: true, + disclosure_required: false, +}; + +const EFFECTFUL: EndpointTrustBoundary = EndpointTrustBoundary { + production_tls_required: true, + native_parse_required: true, + transport_is_not_authority: true, + disclosure_required: false, +}; + +/// V1 runtime endpoints exported without opening network, provider, custody, +/// or state-store effects. +pub const RUNTIME_ENDPOINTS_V1: &[RuntimeEndpointSpecV1] = &[ + RuntimeEndpointSpecV1 { + id: "auths.endpoint.health/1", + operation: None, + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::Health, + method: HttpMethod::Get, + path: "/v1/health", + max_body_bytes: 0, + outcomes: &[OutcomeKind::Completed], + scenario: None, + trust: READ_ONLY, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.version/1", + operation: None, + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::Version, + method: HttpMethod::Get, + path: "/v1/version", + max_body_bytes: 0, + outcomes: &[OutcomeKind::Completed], + scenario: None, + trust: READ_ONLY, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.authorities/1", + operation: Some("auths.operation.create/1"), + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::Authority, + method: HttpMethod::Post, + path: "/v1/authorities", + max_body_bytes: 65_536, + outcomes: &[ + OutcomeKind::Completed, + OutcomeKind::Denied, + OutcomeKind::Indeterminate, + ], + scenario: Some("auths.scenario.rest-effect/1"), + trust: EFFECTFUL, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.executions/1", + operation: Some("auths.operation.execute/1"), + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::ProfileExecution, + method: HttpMethod::Post, + path: "/v1/executions", + max_body_bytes: 262_144, + outcomes: &[ + OutcomeKind::Completed, + OutcomeKind::Denied, + OutcomeKind::Indeterminate, + OutcomeKind::Recoverable, + ], + scenario: Some("auths.scenario.rest-effect/1"), + trust: EFFECTFUL, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.execution-resume/1", + operation: Some("auths.operation.resume/1"), + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::WorkflowRecovery, + method: HttpMethod::Post, + path: "/v1/executions/{execution_id}/resume", + max_body_bytes: 65_536, + outcomes: &[ + OutcomeKind::Completed, + OutcomeKind::Denied, + OutcomeKind::Indeterminate, + OutcomeKind::Recoverable, + OutcomeKind::NotFound, + ], + scenario: Some("auths.scenario.rest-effect/1"), + trust: EFFECTFUL, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.receipt-summary/1", + operation: Some("auths.operation.verify/1"), + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::ReceiptSummary, + method: HttpMethod::Get, + path: "/v1/receipts/{receipt_id}", + max_body_bytes: 0, + outcomes: &[OutcomeKind::Completed, OutcomeKind::NotFound], + scenario: Some("auths.scenario.receipt-verification/1"), + trust: READ_ONLY, + }, + RuntimeEndpointSpecV1 { + id: "auths.endpoint.receipt-disclosure/1", + operation: Some("auths.operation.verify/1"), + page: "auths.page.reference.runtime-api/1", + class: EndpointClass::ReceiptDisclosure, + method: HttpMethod::Post, + path: "/v1/receipts/{receipt_id}/disclosures", + max_body_bytes: 65_536, + outcomes: &[ + OutcomeKind::Completed, + OutcomeKind::Denied, + OutcomeKind::NotFound, + ], + scenario: Some("auths.scenario.receipt-verification/1"), + trust: EndpointTrustBoundary { + disclosure_required: true, + ..EFFECTFUL + }, + }, +]; + +/// Returns the immutable V1 runtime endpoint facts. +#[must_use] +pub const fn runtime_endpoint_facts_v1() -> &'static [RuntimeEndpointSpecV1] { + RUNTIME_ENDPOINTS_V1 +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::BTreeSet; + + #[test] + fn endpoint_identities_and_routes_are_unique() { + let mut identities = BTreeSet::new(); + let mut routes = BTreeSet::new(); + for endpoint in RUNTIME_ENDPOINTS_V1 { + assert!(identities.insert(endpoint.id)); + assert!(routes.insert((endpoint.method as u8, endpoint.path))); + if matches!( + endpoint.class, + EndpointClass::ProfileExecution | EndpointClass::WorkflowRecovery + ) { + assert!(endpoint.scenario.is_some()); + } + } + } +} diff --git a/product/runtime/auths-runtime/src/lib.rs b/product/runtime/auths-runtime/src/lib.rs index 632aa053..2db85564 100644 --- a/product/runtime/auths-runtime/src/lib.rs +++ b/product/runtime/auths-runtime/src/lib.rs @@ -2,6 +2,8 @@ #![forbid(unsafe_code)] +pub mod docs; + use async_trait::async_trait; use auths_codec::context_digest; pub use auths_kernel_runtime::AuthsKernel; diff --git a/product/spec/v1/auths-docs-bundle.schema.json b/product/spec/v1/auths-docs-bundle.schema.json new file mode 100644 index 00000000..e4b47c37 --- /dev/null +++ b/product/spec/v1/auths-docs-bundle.schema.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://auths.dev/spec/v1/auths-docs-bundle.schema.json", + "title": "Auths documentation bundle manifest V1", + "type": "object", + "additionalProperties": false, + "required": ["schema", "contractDigest", "sourceCommit", "files"], + "properties": { + "schema": { "const": "auths.docs.bundle/1" }, + "contractDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "sourceCommit": { "type": "string", "pattern": "^[a-f0-9]{40}$" }, + "files": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["path", "sha256", "bytes"], + "properties": { + "path": { "type": "string", "pattern": "^[a-z0-9][a-z0-9./-]+$" }, + "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "bytes": { "type": "integer", "minimum": 1, "maximum": 16777216 } + } + } + } + } +} diff --git a/product/spec/v1/auths-docs-contract.schema.json b/product/spec/v1/auths-docs-contract.schema.json new file mode 100644 index 00000000..428328a1 --- /dev/null +++ b/product/spec/v1/auths-docs-contract.schema.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://auths.dev/spec/v1/auths-docs-contract.schema.json", + "title": "Auths documentation surface contract V1", + "type": "object", + "additionalProperties": false, + "required": ["schema", "version", "sourceCommit", "semanticFreezeSha256", "operations", "pages", "scenarios", "projections", "runtimeFacts", "digest"], + "properties": { + "schema": { "const": "auths.docs.contract/1" }, + "version": { "const": 1 }, + "sourceCommit": { "type": ["string", "null"] }, + "semanticFreezeSha256": { "$ref": "#/$defs/digest" }, + "digest": { "$ref": "#/$defs/digest" }, + "operations": { + "type": "array", + "items": { "$ref": "#/$defs/operation" } + }, + "pages": { + "type": "array", + "items": { "$ref": "#/$defs/page" } + }, + "scenarios": { + "type": "array", + "items": { "$ref": "#/$defs/scenario" } + }, + "projections": { + "type": "array", + "items": { "$ref": "#/$defs/projection" } + }, + "runtimeFacts": { + "type": "object", + "required": ["schema", "provenance", "endpoints"] + } + }, + "$defs": { + "identity": { + "type": "string", + "maxLength": 128, + "pattern": "^[a-z0-9.-]+/[1-9][0-9]*$" + }, + "digest": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "operation": { + "type": "object", + "additionalProperties": false, + "required": ["id", "verb", "summary", "status"], + "properties": { + "id": { "$ref": "#/$defs/identity" }, + "verb": { "enum": ["create", "delegate", "execute", "resume", "verify"] }, + "summary": { "type": "string", "minLength": 1, "maxLength": 240 }, + "status": { "enum": ["experimental", "stable", "qualified"] } + } + }, + "page": { + "type": "object", + "additionalProperties": false, + "required": ["id", "path", "kind", "title"], + "properties": { + "id": { "$ref": "#/$defs/identity" }, + "path": { "type": "string", "pattern": "^/" }, + "kind": { "enum": ["landing", "guide", "sdk-reference", "runtime-api-reference", "architecture", "operations", "integration", "assurance"] }, + "title": { "type": "string", "minLength": 1, "maxLength": 160 }, + "operations": { "type": "array", "items": { "$ref": "#/$defs/identity" }, "uniqueItems": true }, + "scenarios": { "type": "array", "items": { "$ref": "#/$defs/identity" }, "uniqueItems": true } + } + }, + "scenario": { + "type": "object", + "additionalProperties": false, + "required": ["id", "summary", "languages"], + "properties": { + "id": { "$ref": "#/$defs/identity" }, + "summary": { "type": "string", "minLength": 1, "maxLength": 240 }, + "languages": { "type": "array", "items": { "enum": ["rust", "typescript", "python"] }, "minItems": 1, "uniqueItems": true } + } + }, + "projection": { + "type": "object", + "additionalProperties": false, + "required": ["operation", "language", "package", "entrypoint", "support"], + "properties": { + "operation": { "$ref": "#/$defs/identity" }, + "language": { "enum": ["rust", "typescript", "python"] }, + "package": { "type": "string", "minLength": 1 }, + "entrypoint": { "type": "string", "minLength": 1 }, + "symbol": { "type": "string", "minLength": 1 }, + "support": { "enum": ["supported", "not-supported"] }, + "reason": { "type": "string", "minLength": 1 } + } + } + } +} diff --git a/release/auths-docs-contract-v1.json b/release/auths-docs-contract-v1.json new file mode 100644 index 00000000..f2ba03a9 --- /dev/null +++ b/release/auths-docs-contract-v1.json @@ -0,0 +1,576 @@ +{ + "schema": "auths.docs.contract/1", + "version": 1, + "sourceCommit": null, + "semanticFreezeSha256": "75e787e3f1412e63301761ae3503339b493e1f5fdb2441fede9599a6a9da89a3", + "operations": [ + { + "id": "auths.operation.create/1", + "verb": "create", + "summary": "Create bounded authority for an exact outcome.", + "status": "stable" + }, + { + "id": "auths.operation.delegate/1", + "verb": "delegate", + "summary": "Pass on authority without making it broader.", + "status": "stable" + }, + { + "id": "auths.operation.execute/1", + "verb": "execute", + "summary": "Authorize and perform a sealed effect.", + "status": "stable" + }, + { + "id": "auths.operation.resume/1", + "verb": "resume", + "summary": "Continue an interrupted effect without losing its safety boundary.", + "status": "stable" + }, + { + "id": "auths.operation.verify/1", + "verb": "verify", + "summary": "Verify authority or a receipt without performing an effect.", + "status": "stable" + } + ], + "pages": [ + { + "id": "auths.page.architecture.system-map/1", + "path": "/architecture/system-map/", + "kind": "architecture", + "title": "System map" + }, + { + "id": "auths.page.home/1", + "path": "/", + "kind": "landing", + "title": "Auths documentation" + }, + { + "id": "auths.page.reference.runtime-api/1", + "path": "/reference/runtime-api/", + "kind": "runtime-api-reference", + "title": "Runtime API reference" + }, + { + "id": "auths.page.reference.sdk/1", + "path": "/reference/sdk/", + "kind": "sdk-reference", + "title": "SDK reference", + "operations": [ + "auths.operation.create/1", + "auths.operation.delegate/1", + "auths.operation.execute/1", + "auths.operation.resume/1", + "auths.operation.verify/1" + ] + }, + { + "id": "auths.page.start.delegate-agent/1", + "path": "/start/delegate-to-an-agent/", + "kind": "guide", + "title": "Delegate to an agent", + "operations": [ + "auths.operation.delegate/1" + ], + "scenarios": [ + "auths.scenario.delegation/1" + ] + }, + { + "id": "auths.page.start.rest-effect/1", + "path": "/start/protect-a-rest-effect/", + "kind": "guide", + "title": "Protect a REST effect", + "operations": [ + "auths.operation.create/1", + "auths.operation.execute/1" + ], + "scenarios": [ + "auths.scenario.rest-effect/1" + ] + }, + { + "id": "auths.page.start.verify-receipt/1", + "path": "/start/verify-a-receipt/", + "kind": "guide", + "title": "Verify a receipt", + "operations": [ + "auths.operation.verify/1" + ], + "scenarios": [ + "auths.scenario.receipt-verification/1" + ] + } + ], + "scenarios": [ + { + "id": "auths.scenario.agent-delegation/1", + "summary": "Delegate one agent action and reject authority widening.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.approved-plan/1", + "summary": "Execute one exact approved plan and reject member substitution.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.delegation/1", + "summary": "Delegate narrower authority and reject widening.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.identity-swap/1", + "summary": "Run one workflow across two signature suites and reject a mislabelled suite.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.local-rest-effect/1", + "summary": "Complete one exact local REST-shaped effect and reject mutated bytes.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.offline-verification/1", + "summary": "Verify authority and a receipt offline and reject the wrong context.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.receipt-verification/1", + "summary": "Verify an execution receipt without performing an effect.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.recovery/1", + "summary": "Resume one recoverable execution and prohibit a fresh retry.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.rest-effect/1", + "summary": "Authorize one bounded REST effect and return a receipt.", + "languages": [ + "rust", + "typescript", + "python" + ] + }, + { + "id": "auths.scenario.runtime-effect/1", + "summary": "Complete one runtime effect and deny exact replay.", + "languages": [ + "rust", + "typescript", + "python" + ] + } + ], + "claims": [ + { + "id": "auths.claim.approval-binding/1", + "statement": "Approval is bound to exact plan context and cannot authorize substituted plan bytes.", + "status": "passing", + "evidence": "bindings/recipes/experience-evidence.json", + "evidenceSha256": "a8ba8a06a3979d62bab446f1bc2469e328e98e485a344a8a36d07ee0f2013331", + "scope": "Maintained approval-plan signing requests, responses, and substitution fixtures.", + "limitation": "The application remains responsible for approver identity, user experience, and organizational policy.", + "reproduction": [ + "cargo xtask sdk-experience" + ] + }, + { + "id": "auths.claim.attenuation/1", + "statement": "Delegated authority cannot become broader than its parent under the maintained model and adversarial fixtures.", + "status": "passing", + "evidence": "formal/qualification.lean", + "evidenceSha256": "fb1fd17d377194e96f98313412052f82fbb43cb594b12eb6a9fa0e0dce3ce70c", + "scope": "Attenuation relations represented by the maintained formal model and protocol profile.", + "limitation": "The claim covers the modelled fields and maintained protocol profile, not arbitrary application-defined semantics.", + "reproduction": [ + "cargo xtask formal" + ] + }, + { + "id": "auths.claim.bounded-disclosure/1", + "statement": "Receipt inspection defaults to opaque or bounded views and requires authority for full disclosure.", + "status": "passing", + "evidence": "release/docs/runtime-facts-v1.json", + "evidenceSha256": "3229ccc5a4adbcdfd4b55bdca58ab9e7e5c333719aeff3a0dba54976e6fef1f1", + "scope": "Maintained receipt summary and disclosure operations and their public runtime contract.", + "limitation": "Deployment retention, access control, and downstream handling remain application responsibilities.", + "reproduction": [ + "cargo xtask product-conformance" + ] + }, + { + "id": "auths.claim.closed-gateway/1", + "statement": "Maintained product workflows reach provider adapters only through opaque native-authorized commands.", + "status": "passing", + "evidence": "release/semantic-freeze.json", + "evidenceSha256": "75e787e3f1412e63301761ae3503339b493e1f5fdb2441fede9599a6a9da89a3", + "scope": "Maintained execution workflows and their opaque native command and gateway boundary.", + "limitation": "Application-owned adapters can still be implemented unsafely outside the maintained boundary.", + "reproduction": [ + "cargo xtask product-waist-conformance" + ] + }, + { + "id": "auths.claim.cross-language-parity/1", + "statement": "Maintained Rust, TypeScript, and Python scenarios target identical stable semantic outcomes.", + "status": "passing", + "evidence": "release/docs/scenarios.toml", + "evidenceSha256": "f056e57acb5dbad67ef5ed5076bdee388a82e73b7e6a6af53b82c226ccd552da", + "scope": "The maintained installed-artifact scenarios declared for Rust, TypeScript, and Python.", + "limitation": "Scenario parity covers maintained workflows and versions, not every possible application composition.", + "reproduction": [ + "cargo xtask cross-language" + ] + }, + { + "id": "auths.claim.lifecycle-state/1", + "statement": "Maintained runtime paths preserve replay, use, budget, and recovery distinctions.", + "status": "passing", + "evidence": "bindings/recipes/experience-evidence.json", + "evidenceSha256": "a8ba8a06a3979d62bab446f1bc2469e328e98e485a344a8a36d07ee0f2013331", + "scope": "Maintained runtime and installed-SDK workflows for replay, use, budget, reservation, and recovery outcomes.", + "limitation": "Production guarantees also depend on the selected durable store and its deployment.", + "reproduction": [ + "cargo xtask sdk-experience" + ] + }, + { + "id": "auths.claim.native-semantic-owner/1", + "statement": "Rust owns protocol meaning used by Rust, TypeScript, and Python projections.", + "status": "passing", + "evidence": "release/semantic-freeze.json", + "evidenceSha256": "75e787e3f1412e63301761ae3503339b493e1f5fdb2441fede9599a6a9da89a3", + "scope": "The declared protocol and product semantic identities consumed by maintained Rust, TypeScript, and Python surfaces.", + "limitation": "The semantic freeze detects declared semantic drift; it is not a proof that every implementation is defect-free.", + "reproduction": [ + "cargo xtask semantic-freeze" + ] + }, + { + "id": "auths.claim.supply-chain/1", + "statement": "The assessed release builder satisfies the recorded SLSA Build Level 3 requirements.", + "status": "passing", + "evidence": "release/slsa-build-level-3-assessment.json", + "evidenceSha256": "49d5a096915d49058c8c66f29c5c7f59181caa0783d4724322068de6c5c3f6bf", + "scope": "The assessed GitHub release builder and recorded SLSA 1.2 Build Level 3 controls.", + "limitation": "This is a repository-owner delegated build assessment, not an independent security audit or source-correctness proof.", + "reproduction": [ + "cargo test -p xtask release_control::tests::checked_in_slsa_assessment_matches_builder_bytes" + ] + } + ], + "projections": [ + { + "operation": "auths.operation.create/1", + "language": "rust", + "package": "auths-author", + "entrypoint": "auths_author", + "symbol": "prepare_grant", + "support": "supported" + }, + { + "operation": "auths.operation.create/1", + "language": "typescript", + "package": "@auths-dev/sdk", + "entrypoint": "./integrations", + "symbol": "development.createAuths", + "support": "supported" + }, + { + "operation": "auths.operation.create/1", + "language": "python", + "package": "auths", + "entrypoint": "auths.integrations", + "symbol": "development.create_auths", + "support": "supported" + }, + { + "operation": "auths.operation.delegate/1", + "language": "rust", + "package": "auths-author", + "entrypoint": "auths_author", + "symbol": "plan_child_grant", + "support": "supported" + }, + { + "operation": "auths.operation.delegate/1", + "language": "typescript", + "package": "@auths-dev/sdk", + "entrypoint": ".", + "symbol": "Auths.delegate", + "support": "supported" + }, + { + "operation": "auths.operation.delegate/1", + "language": "python", + "package": "auths", + "entrypoint": "auths", + "symbol": "Auths.delegate", + "support": "supported" + }, + { + "operation": "auths.operation.execute/1", + "language": "rust", + "package": "auths-runtime", + "entrypoint": "auths_runtime::McpAuthorizationService", + "symbol": "ProofExchangeService::submit_action", + "support": "supported" + }, + { + "operation": "auths.operation.execute/1", + "language": "typescript", + "package": "@auths-dev/sdk", + "entrypoint": ".", + "symbol": "Auths.execute", + "support": "supported" + }, + { + "operation": "auths.operation.execute/1", + "language": "python", + "package": "auths", + "entrypoint": "auths", + "symbol": "Auths.execute", + "support": "supported" + }, + { + "operation": "auths.operation.resume/1", + "language": "rust", + "package": "auths-profile-mcp", + "entrypoint": "auths_profile_mcp::McpSession", + "symbol": "McpSession::resume", + "support": "supported" + }, + { + "operation": "auths.operation.resume/1", + "language": "typescript", + "package": "@auths-dev/sdk", + "entrypoint": ".", + "symbol": "Auths.resume", + "support": "supported" + }, + { + "operation": "auths.operation.resume/1", + "language": "python", + "package": "auths", + "entrypoint": "auths", + "symbol": "Auths.resume", + "support": "supported" + }, + { + "operation": "auths.operation.verify/1", + "language": "rust", + "package": "auths-sdk", + "entrypoint": "auths_sdk::Verifier", + "symbol": "Verifier::verify", + "support": "supported" + }, + { + "operation": "auths.operation.verify/1", + "language": "typescript", + "package": "@auths-dev/sdk", + "entrypoint": "./verify", + "symbol": "loadVerifier", + "support": "supported" + }, + { + "operation": "auths.operation.verify/1", + "language": "python", + "package": "auths", + "entrypoint": "auths.verify", + "symbol": "verify", + "support": "supported" + } + ], + "runtimeFacts": { + "schema": "auths.runtime-docs-facts/1", + "provenance": { + "kind": "compiled-registry", + "subject": "auths.product.runtime-endpoints/1", + "owner": "product/runtime/auths-runtime/src/docs.rs" + }, + "endpoints": [ + { + "id": "auths.endpoint.health/1", + "operation": null, + "page": "auths.page.reference.runtime-api/1", + "class": "health", + "method": "GET", + "path": "/v1/health", + "maxBodyBytes": 0, + "outcomes": [ + "completed" + ], + "scenario": null, + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": false, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.version/1", + "operation": null, + "page": "auths.page.reference.runtime-api/1", + "class": "version", + "method": "GET", + "path": "/v1/version", + "maxBodyBytes": 0, + "outcomes": [ + "completed" + ], + "scenario": null, + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": false, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.authorities/1", + "operation": "auths.operation.create/1", + "page": "auths.page.reference.runtime-api/1", + "class": "authority", + "method": "POST", + "path": "/v1/authorities", + "maxBodyBytes": 65536, + "outcomes": [ + "completed", + "denied", + "indeterminate" + ], + "scenario": "auths.scenario.rest-effect/1", + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": true, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.executions/1", + "operation": "auths.operation.execute/1", + "page": "auths.page.reference.runtime-api/1", + "class": "profile-execution", + "method": "POST", + "path": "/v1/executions", + "maxBodyBytes": 262144, + "outcomes": [ + "completed", + "denied", + "indeterminate", + "recoverable" + ], + "scenario": "auths.scenario.rest-effect/1", + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": true, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.execution-resume/1", + "operation": "auths.operation.resume/1", + "page": "auths.page.reference.runtime-api/1", + "class": "workflow-recovery", + "method": "POST", + "path": "/v1/executions/{execution_id}/resume", + "maxBodyBytes": 65536, + "outcomes": [ + "completed", + "denied", + "indeterminate", + "recoverable", + "not-found" + ], + "scenario": "auths.scenario.rest-effect/1", + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": true, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.receipt-summary/1", + "operation": "auths.operation.verify/1", + "page": "auths.page.reference.runtime-api/1", + "class": "receipt-summary", + "method": "GET", + "path": "/v1/receipts/{receipt_id}", + "maxBodyBytes": 0, + "outcomes": [ + "completed", + "not-found" + ], + "scenario": "auths.scenario.receipt-verification/1", + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": false, + "transportIsNotAuthority": true, + "disclosureRequired": false + } + }, + { + "id": "auths.endpoint.receipt-disclosure/1", + "operation": "auths.operation.verify/1", + "page": "auths.page.reference.runtime-api/1", + "class": "receipt-disclosure", + "method": "POST", + "path": "/v1/receipts/{receipt_id}/disclosures", + "maxBodyBytes": 65536, + "outcomes": [ + "completed", + "denied", + "not-found" + ], + "scenario": "auths.scenario.receipt-verification/1", + "trust": { + "productionTlsRequired": true, + "nativeParseRequired": true, + "transportIsNotAuthority": true, + "disclosureRequired": true + } + } + ] + }, + "digest": "8817d78d2db3c8640f227ca1237b0b53fd8d991515d5c9b2def14319a85b5b90" +} diff --git a/release/docs/claims.toml b/release/docs/claims.toml new file mode 100644 index 00000000..18d15738 --- /dev/null +++ b/release/docs/claims.toml @@ -0,0 +1,73 @@ +schema = "auths.docs.claims/1" + +[[claim]] +id = "auths.claim.native-semantic-owner/1" +statement = "Rust owns protocol meaning used by Rust, TypeScript, and Python projections." +status = "passing" +evidence = "release/semantic-freeze.json" +scope = "The declared protocol and product semantic identities consumed by maintained Rust, TypeScript, and Python surfaces." +limitation = "The semantic freeze detects declared semantic drift; it is not a proof that every implementation is defect-free." +reproduction = ["cargo xtask semantic-freeze"] + +[[claim]] +id = "auths.claim.attenuation/1" +statement = "Delegated authority cannot become broader than its parent under the maintained model and adversarial fixtures." +status = "passing" +evidence = "formal/qualification.lean" +scope = "Attenuation relations represented by the maintained formal model and protocol profile." +limitation = "The claim covers the modelled fields and maintained protocol profile, not arbitrary application-defined semantics." +reproduction = ["cargo xtask formal"] + +[[claim]] +id = "auths.claim.lifecycle-state/1" +statement = "Maintained runtime paths preserve replay, use, budget, and recovery distinctions." +status = "passing" +evidence = "bindings/recipes/experience-evidence.json" +scope = "Maintained runtime and installed-SDK workflows for replay, use, budget, reservation, and recovery outcomes." +limitation = "Production guarantees also depend on the selected durable store and its deployment." +reproduction = ["cargo xtask sdk-experience"] + +[[claim]] +id = "auths.claim.approval-binding/1" +statement = "Approval is bound to exact plan context and cannot authorize substituted plan bytes." +status = "passing" +evidence = "bindings/recipes/experience-evidence.json" +scope = "Maintained approval-plan signing requests, responses, and substitution fixtures." +limitation = "The application remains responsible for approver identity, user experience, and organizational policy." +reproduction = ["cargo xtask sdk-experience"] + +[[claim]] +id = "auths.claim.closed-gateway/1" +statement = "Maintained product workflows reach provider adapters only through opaque native-authorized commands." +status = "passing" +evidence = "release/semantic-freeze.json" +scope = "Maintained execution workflows and their opaque native command and gateway boundary." +limitation = "Application-owned adapters can still be implemented unsafely outside the maintained boundary." +reproduction = ["cargo xtask product-waist-conformance"] + +[[claim]] +id = "auths.claim.bounded-disclosure/1" +statement = "Receipt inspection defaults to opaque or bounded views and requires authority for full disclosure." +status = "passing" +evidence = "release/docs/runtime-facts-v1.json" +scope = "Maintained receipt summary and disclosure operations and their public runtime contract." +limitation = "Deployment retention, access control, and downstream handling remain application responsibilities." +reproduction = ["cargo xtask product-conformance"] + +[[claim]] +id = "auths.claim.cross-language-parity/1" +statement = "Maintained Rust, TypeScript, and Python scenarios target identical stable semantic outcomes." +status = "passing" +evidence = "release/docs/scenarios.toml" +scope = "The maintained installed-artifact scenarios declared for Rust, TypeScript, and Python." +limitation = "Scenario parity covers maintained workflows and versions, not every possible application composition." +reproduction = ["cargo xtask cross-language"] + +[[claim]] +id = "auths.claim.supply-chain/1" +statement = "The assessed release builder satisfies the recorded SLSA Build Level 3 requirements." +status = "passing" +evidence = "release/slsa-build-level-3-assessment.json" +scope = "The assessed GitHub release builder and recorded SLSA 1.2 Build Level 3 controls." +limitation = "This is a repository-owner delegated build assessment, not an independent security audit or source-correctness proof." +reproduction = ["cargo test -p xtask release_control::tests::checked_in_slsa_assessment_matches_builder_bytes"] diff --git a/release/docs/deployment-manifest.schema.json b/release/docs/deployment-manifest.schema.json new file mode 100644 index 00000000..b785c1c3 --- /dev/null +++ b/release/docs/deployment-manifest.schema.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://auths.dev/spec/v1/auths-docs-deployment-manifest.schema.json", + "type": "object", + "additionalProperties": false, + "required": ["schema", "productCommit", "docsCommit", "contractDigest", "bundleDigest", "staticOutputDigest", "target", "promotedAt", "priorDeploymentDigest"], + "properties": { + "schema": { "const": "auths.docs.deployment/1" }, + "productCommit": { "type": "string", "pattern": "^[a-f0-9]{40}$" }, + "docsCommit": { "type": "string", "pattern": "^[a-f0-9]{40}$" }, + "contractDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "bundleDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "staticOutputDigest": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, + "target": { "type": "string", "minLength": 1, "maxLength": 128 }, + "promotedAt": { "type": "string", "format": "date-time" }, + "priorDeploymentDigest": { "type": ["string", "null"], "pattern": "^[a-f0-9]{64}$" } + } +} diff --git a/release/docs/operations.toml b/release/docs/operations.toml new file mode 100644 index 00000000..a1e73b59 --- /dev/null +++ b/release/docs/operations.toml @@ -0,0 +1,31 @@ +schema = "auths.docs.operations/1" + +[[operation]] +id = "auths.operation.create/1" +verb = "create" +summary = "Create bounded authority for an exact outcome." +status = "stable" + +[[operation]] +id = "auths.operation.delegate/1" +verb = "delegate" +summary = "Pass on authority without making it broader." +status = "stable" + +[[operation]] +id = "auths.operation.execute/1" +verb = "execute" +summary = "Authorize and perform a sealed effect." +status = "stable" + +[[operation]] +id = "auths.operation.resume/1" +verb = "resume" +summary = "Continue an interrupted effect without losing its safety boundary." +status = "stable" + +[[operation]] +id = "auths.operation.verify/1" +verb = "verify" +summary = "Verify authority or a receipt without performing an effect." +status = "stable" diff --git a/release/docs/pages.toml b/release/docs/pages.toml new file mode 100644 index 00000000..734d6db2 --- /dev/null +++ b/release/docs/pages.toml @@ -0,0 +1,50 @@ +schema = "auths.docs.pages/1" + +[[page]] +id = "auths.page.home/1" +path = "/" +kind = "landing" +title = "Auths documentation" + +[[page]] +id = "auths.page.start.rest-effect/1" +path = "/start/protect-a-rest-effect/" +kind = "guide" +title = "Protect a REST effect" +operations = ["auths.operation.create/1", "auths.operation.execute/1"] +scenarios = ["auths.scenario.rest-effect/1"] + +[[page]] +id = "auths.page.start.delegate-agent/1" +path = "/start/delegate-to-an-agent/" +kind = "guide" +title = "Delegate to an agent" +operations = ["auths.operation.delegate/1"] +scenarios = ["auths.scenario.delegation/1"] + +[[page]] +id = "auths.page.start.verify-receipt/1" +path = "/start/verify-a-receipt/" +kind = "guide" +title = "Verify a receipt" +operations = ["auths.operation.verify/1"] +scenarios = ["auths.scenario.receipt-verification/1"] + +[[page]] +id = "auths.page.reference.sdk/1" +path = "/reference/sdk/" +kind = "sdk-reference" +title = "SDK reference" +operations = ["auths.operation.create/1", "auths.operation.delegate/1", "auths.operation.execute/1", "auths.operation.resume/1", "auths.operation.verify/1"] + +[[page]] +id = "auths.page.reference.runtime-api/1" +path = "/reference/runtime-api/" +kind = "runtime-api-reference" +title = "Runtime API reference" + +[[page]] +id = "auths.page.architecture.system-map/1" +path = "/architecture/system-map/" +kind = "architecture" +title = "System map" diff --git a/release/docs/projections-python.toml b/release/docs/projections-python.toml new file mode 100644 index 00000000..5edbddc3 --- /dev/null +++ b/release/docs/projections-python.toml @@ -0,0 +1,37 @@ +schema = "auths.docs.projections/1" +language = "python" + +[[projection]] +operation = "auths.operation.create/1" +package = "auths" +entrypoint = "auths.integrations" +symbol = "development.create_auths" +support = "supported" + +[[projection]] +operation = "auths.operation.delegate/1" +package = "auths" +entrypoint = "auths" +symbol = "Auths.delegate" +support = "supported" + +[[projection]] +operation = "auths.operation.execute/1" +package = "auths" +entrypoint = "auths" +symbol = "Auths.execute" +support = "supported" + +[[projection]] +operation = "auths.operation.resume/1" +package = "auths" +entrypoint = "auths" +symbol = "Auths.resume" +support = "supported" + +[[projection]] +operation = "auths.operation.verify/1" +package = "auths" +entrypoint = "auths.verify" +symbol = "verify" +support = "supported" diff --git a/release/docs/projections-rust.toml b/release/docs/projections-rust.toml new file mode 100644 index 00000000..456a062a --- /dev/null +++ b/release/docs/projections-rust.toml @@ -0,0 +1,37 @@ +schema = "auths.docs.projections/1" +language = "rust" + +[[projection]] +operation = "auths.operation.create/1" +package = "auths-author" +entrypoint = "auths_author" +symbol = "prepare_grant" +support = "supported" + +[[projection]] +operation = "auths.operation.delegate/1" +package = "auths-author" +entrypoint = "auths_author" +symbol = "plan_child_grant" +support = "supported" + +[[projection]] +operation = "auths.operation.execute/1" +package = "auths-runtime" +entrypoint = "auths_runtime::McpAuthorizationService" +symbol = "ProofExchangeService::submit_action" +support = "supported" + +[[projection]] +operation = "auths.operation.resume/1" +package = "auths-profile-mcp" +entrypoint = "auths_profile_mcp::McpSession" +symbol = "McpSession::resume" +support = "supported" + +[[projection]] +operation = "auths.operation.verify/1" +package = "auths-sdk" +entrypoint = "auths_sdk::Verifier" +symbol = "Verifier::verify" +support = "supported" diff --git a/release/docs/projections-typescript.toml b/release/docs/projections-typescript.toml new file mode 100644 index 00000000..3f763120 --- /dev/null +++ b/release/docs/projections-typescript.toml @@ -0,0 +1,37 @@ +schema = "auths.docs.projections/1" +language = "typescript" + +[[projection]] +operation = "auths.operation.create/1" +package = "@auths-dev/sdk" +entrypoint = "./integrations" +symbol = "development.createAuths" +support = "supported" + +[[projection]] +operation = "auths.operation.delegate/1" +package = "@auths-dev/sdk" +entrypoint = "." +symbol = "Auths.delegate" +support = "supported" + +[[projection]] +operation = "auths.operation.execute/1" +package = "@auths-dev/sdk" +entrypoint = "." +symbol = "Auths.execute" +support = "supported" + +[[projection]] +operation = "auths.operation.resume/1" +package = "@auths-dev/sdk" +entrypoint = "." +symbol = "Auths.resume" +support = "supported" + +[[projection]] +operation = "auths.operation.verify/1" +package = "@auths-dev/sdk" +entrypoint = "./verify" +symbol = "loadVerifier" +support = "supported" diff --git a/release/docs/public-docs-report.json b/release/docs/public-docs-report.json new file mode 100644 index 00000000..0349b523 --- /dev/null +++ b/release/docs/public-docs-report.json @@ -0,0 +1,41 @@ +{ + "schema": "auths.public-docs-report/1", + "policy": "auths.public-docs-policy/1", + "tiers": [ + { + "name": "P0", + "operationCount": 5, + "requiredSections": [ + "summary", + "outcomes", + "security", + "scenario" + ] + }, + { + "name": "P1", + "operationCount": 0, + "requiredSections": [ + "summary" + ] + }, + { + "name": "P2", + "operationCount": 0, + "requiredSections": [ + "summary", + "invariants" + ] + } + ], + "languages": [ + "rust", + "typescript", + "python" + ], + "p0": { + "required": 5, + "documented": 5, + "missing": [] + } +} diff --git a/release/docs/runtime-facts-v1.json b/release/docs/runtime-facts-v1.json new file mode 100644 index 00000000..9900c7e3 --- /dev/null +++ b/release/docs/runtime-facts-v1.json @@ -0,0 +1,17 @@ +{ + "schema": "auths.runtime-docs-facts/1", + "provenance": { + "kind": "compiled-registry", + "subject": "auths.product.runtime-endpoints/1", + "owner": "product/runtime/auths-runtime/src/docs.rs" + }, + "endpoints": [ + {"id":"auths.endpoint.health/1","operation":null,"page":"auths.page.reference.runtime-api/1","class":"health","method":"GET","path":"/v1/health","maxBodyBytes":0,"outcomes":["completed"],"scenario":null,"trust":{"productionTlsRequired":true,"nativeParseRequired":false,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.version/1","operation":null,"page":"auths.page.reference.runtime-api/1","class":"version","method":"GET","path":"/v1/version","maxBodyBytes":0,"outcomes":["completed"],"scenario":null,"trust":{"productionTlsRequired":true,"nativeParseRequired":false,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.authorities/1","operation":"auths.operation.create/1","page":"auths.page.reference.runtime-api/1","class":"authority","method":"POST","path":"/v1/authorities","maxBodyBytes":65536,"outcomes":["completed","denied","indeterminate"],"scenario":"auths.scenario.rest-effect/1","trust":{"productionTlsRequired":true,"nativeParseRequired":true,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.executions/1","operation":"auths.operation.execute/1","page":"auths.page.reference.runtime-api/1","class":"profile-execution","method":"POST","path":"/v1/executions","maxBodyBytes":262144,"outcomes":["completed","denied","indeterminate","recoverable"],"scenario":"auths.scenario.rest-effect/1","trust":{"productionTlsRequired":true,"nativeParseRequired":true,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.execution-resume/1","operation":"auths.operation.resume/1","page":"auths.page.reference.runtime-api/1","class":"workflow-recovery","method":"POST","path":"/v1/executions/{execution_id}/resume","maxBodyBytes":65536,"outcomes":["completed","denied","indeterminate","recoverable","not-found"],"scenario":"auths.scenario.rest-effect/1","trust":{"productionTlsRequired":true,"nativeParseRequired":true,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.receipt-summary/1","operation":"auths.operation.verify/1","page":"auths.page.reference.runtime-api/1","class":"receipt-summary","method":"GET","path":"/v1/receipts/{receipt_id}","maxBodyBytes":0,"outcomes":["completed","not-found"],"scenario":"auths.scenario.receipt-verification/1","trust":{"productionTlsRequired":true,"nativeParseRequired":false,"transportIsNotAuthority":true,"disclosureRequired":false}}, + {"id":"auths.endpoint.receipt-disclosure/1","operation":"auths.operation.verify/1","page":"auths.page.reference.runtime-api/1","class":"receipt-disclosure","method":"POST","path":"/v1/receipts/{receipt_id}/disclosures","maxBodyBytes":65536,"outcomes":["completed","denied","not-found"],"scenario":"auths.scenario.receipt-verification/1","trust":{"productionTlsRequired":true,"nativeParseRequired":true,"transportIsNotAuthority":true,"disclosureRequired":true}} + ] +} diff --git a/release/docs/scenarios.toml b/release/docs/scenarios.toml new file mode 100644 index 00000000..486148bf --- /dev/null +++ b/release/docs/scenarios.toml @@ -0,0 +1,51 @@ +schema = "auths.docs.scenarios/1" + +[[scenario]] +id = "auths.scenario.rest-effect/1" +summary = "Authorize one bounded REST effect and return a receipt." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.delegation/1" +summary = "Delegate narrower authority and reject widening." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.receipt-verification/1" +summary = "Verify an execution receipt without performing an effect." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.local-rest-effect/1" +summary = "Complete one exact local REST-shaped effect and reject mutated bytes." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.runtime-effect/1" +summary = "Complete one runtime effect and deny exact replay." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.agent-delegation/1" +summary = "Delegate one agent action and reject authority widening." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.approved-plan/1" +summary = "Execute one exact approved plan and reject member substitution." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.offline-verification/1" +summary = "Verify authority and a receipt offline and reject the wrong context." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.recovery/1" +summary = "Resume one recoverable execution and prohibit a fresh retry." +languages = ["rust", "typescript", "python"] + +[[scenario]] +id = "auths.scenario.identity-swap/1" +summary = "Run one workflow across two signature suites and reject a mislabelled suite." +languages = ["rust", "typescript", "python"] diff --git a/release/fixtures/docs/README.md b/release/fixtures/docs/README.md new file mode 100644 index 00000000..d02282d6 --- /dev/null +++ b/release/fixtures/docs/README.md @@ -0,0 +1,5 @@ +# Documentation bundle fixture + +`cargo xtask docs-bundle target/docs-bundle` builds the maintained fixture from +the current documentation contract and installed-surface snapshots. The bundle +manifest is strict, bounded, checksum-addressed, and tied to the source commit. diff --git a/release/release-subjects.toml b/release/release-subjects.toml index 80ab414b..7eeaaee6 100644 --- a/release/release-subjects.toml +++ b/release/release-subjects.toml @@ -54,6 +54,22 @@ reproducibility = "byte-identical" producer = "AP32-PR4 before detached signed provenance; provenance is stored beside the archive to avoid a self-referential digest" publication = "GitHub prerelease only after exact-manifest authorization" +[[families]] +id = "documentation-contract" +coordinate = "auths-docs-contract-v1.json" +media_type = "application/vnd.auths.docs-contract+json" +reproducibility = "byte-identical" +producer = "cargo xtask docs-contract" +publication = "Contained by the source and documentation bundles; consumed by auths-dev/auths-docs by digest" + +[[families]] +id = "documentation-bundle" +coordinate = "auths-docs-bundle-v1.tar.zst" +media_type = "application/zstd" +reproducibility = "byte-identical for a fixed source commit" +producer = "cargo xtask docs-bundle" +publication = "Immutable release artifact consumed by auths-dev/auths-docs by checksum" + [[excluded]] id = "domain-integrations" reason = "Domain packages, demos, benchmarks, testkits, fuzz crates, internal tools, CLIs, hosted services, and OCI images are outside the lean first-RC catalogue." diff --git a/release/semantic-freeze.json b/release/semantic-freeze.json index 7970feb5..2f2cb0cc 100644 --- a/release/semantic-freeze.json +++ b/release/semantic-freeze.json @@ -1,6 +1,6 @@ { "schema": "auths.semantic-freeze/1", - "freezeVersion": 84, + "freezeVersion": 86, "publicSurface": { "rustRoots": [ "auths", @@ -593,7 +593,7 @@ }, { "id": "auths.portable-abi-bindings", - "version": 43, + "version": 44, "classification": "frozen-meaning", "categories": [ "portable-abi", @@ -610,7 +610,7 @@ "core/crates/auths-model/src/lib.rs", "core/spec/v1/auths-proof.cddl" ], - "sha256": "d28ad9cbc0194491c6b81f451345bbada0f9b784f8baa6ca3e86dab5a81ae7c2" + "sha256": "9548bfacd012fbca514a3c76889be95eb30348fa15f6a3f68705b8d861b8c430" }, { "id": "auths.product.bounded-domains", @@ -685,6 +685,24 @@ ], "sha256": "51a37c092bc0418e67cb027d3cb1fd72bc16a5a9f6be0cb247202a97dc4b846b" }, + { + "id": "auths.product.documentation-surface", + "version": 2, + "classification": "frozen-meaning", + "categories": [ + "operation-identities", + "page-identities", + "scenario-identities", + "language-projections", + "documentation-contract-schema" + ], + "owners": [ + "product/spec/v1/auths-docs-contract.schema.json", + "release/docs", + "xtask/src/docs_contract.rs" + ], + "sha256": "5b5fb609a47be754c8410f99dc70f75db8f01879ceb8f6bf2145009c022b251e" + }, { "id": "auths.product.error-recovery-contract", "version": 8, @@ -711,7 +729,7 @@ }, { "id": "auths.product.facade", - "version": 7, + "version": 8, "classification": "frozen-meaning", "categories": [ "create", @@ -726,7 +744,7 @@ "bindings/typescript/src/product.ts", "bindings/typescript/src/profiles/mcp/index.ts" ], - "sha256": "f23d0d9476fa19bde76f073162502ef84225839567cfee3c9273b83cc14673d5" + "sha256": "c0f72231ea8c8c862424eca8b441f2c5af4b5bf1eafec8ef4027b5abdebf9fdc" }, { "id": "auths.product.lifecycle", @@ -792,7 +810,7 @@ }, { "id": "auths.product.public-sdk-contract", - "version": 29, + "version": 30, "classification": "frozen-meaning", "categories": [ "rust-sdk-contract", @@ -809,7 +827,7 @@ "product/runtime/auths-runtime/src", "product/sdk/auths-sdk/src" ], - "sha256": "2b180adc914e597f6adad2ad440298e7d238abcaf83d05664eb2b8daef3ce2a0" + "sha256": "b664fc6ab73bf54c15cb7c288a6d06e1e4eeade869f35642a6d3d0c0f9b21f1c" }, { "id": "auths.product.receipts", @@ -911,7 +929,7 @@ }, { "id": "auths.release.public-surface", - "version": 84, + "version": 86, "classification": "release-metadata", "categories": [ "package-names", @@ -998,7 +1016,7 @@ "xtask/src/release_control.rs", "xtask/src/semantic_freeze.rs" ], - "sha256": "9ca7ba01a718a48ad3eda33fbd19592f4348ee939fdc4c376c52339173dda4a1" + "sha256": "f535b2e6e0c8305d2528ce9c99791e69180fa013eaa33e6f49c9718d9f19b1a8" } ] } diff --git a/rust-toolchain.docs.toml b/rust-toolchain.docs.toml new file mode 100644 index 00000000..99920c10 --- /dev/null +++ b/rust-toolchain.docs.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.90.0" +profile = "minimal" +components = ["rust-docs", "rustfmt"] diff --git a/tools/docs-extractor/README.md b/tools/docs-extractor/README.md new file mode 100644 index 00000000..c5ab2c0e --- /dev/null +++ b/tools/docs-extractor/README.md @@ -0,0 +1,6 @@ +# Documentation extractors + +The release builder runs language-native extractors against installed artifacts, +then `cargo xtask docs-bundle` normalizes their bounded output. Extractors emit +facts only: symbols, signatures, source documentation, stable operation joins, +and package provenance. Website prose does not enter this directory. diff --git a/xtask/src/checks.rs b/xtask/src/checks.rs index b3d85f3f..8be5314d 100644 --- a/xtask/src/checks.rs +++ b/xtask/src/checks.rs @@ -16,6 +16,8 @@ pub(crate) fn ci_authoritative() -> Result<(), String> { semantic_freeze(false)?; sdk_experience(false)?; sdk_vocabulary()?; + docs_contract(Vec::new())?; + public_docs(false)?; error_registry(false)?; mcp_session_contract(false)?; mechanism_conformance(false)?; diff --git a/xtask/src/docs_bundle.rs b/xtask/src/docs_bundle.rs new file mode 100644 index 00000000..d0074c52 --- /dev/null +++ b/xtask/src/docs_bundle.rs @@ -0,0 +1,139 @@ +use crate::*; +use std::io::Write as _; + +const MEMBERS: &[(&str, &str)] = &[ + ("contract.json", "release/auths-docs-contract-v1.json"), + ("runtime-facts.json", "release/docs/runtime-facts-v1.json"), + ( + "public-docs-report.json", + "release/docs/public-docs-report.json", + ), + ( + "typescript-public-api.txt", + "bindings/typescript/api/public-api.txt", + ), + ( + "python-public-api.txt", + "bindings/python/api/public-api.txt", + ), + ("public-topology.json", "bindings/public-topology-v1.json"), +]; + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct BundleManifest { + schema: &'static str, + contract_digest: String, + source_commit: String, + files: Vec, +} + +#[derive(Serialize)] +struct BundleMember { + path: String, + sha256: String, + bytes: usize, +} + +pub(crate) fn docs_bundle(arguments: Vec) -> Result<(), String> { + let mut check = false; + let mut output = None; + for argument in arguments { + if argument == "--check" { + check = true; + } else if output.replace(PathBuf::from(&argument)).is_some() { + return Err("docs-bundle accepts one output directory".to_owned()); + } + } + let output = output.ok_or("usage: cargo xtask docs-bundle [--check]")?; + if output.exists() && !output.is_dir() { + return Err(format!( + "docs bundle output is not a directory: {}", + output.display() + )); + } + fs::create_dir_all(&output) + .map_err(|error| format!("could not create {}: {error}", output.display()))?; + + let contract: Value = serde_json::from_slice( + &fs::read(root().join("release/auths-docs-contract-v1.json")) + .map_err(|error| format!("could not read docs contract: {error}"))?, + ) + .map_err(|error| format!("could not parse docs contract: {error}"))?; + let contract_digest = contract["digest"] + .as_str() + .ok_or("docs contract has no digest")? + .to_owned(); + let source_commit = command_output_in("git", &["rev-parse", "HEAD"], &root(), None)? + .trim() + .to_owned(); + + let mut files = Vec::new(); + for (bundle_path, source_path) in MEMBERS { + let bytes = fs::read(root().join(source_path)) + .map_err(|error| format!("could not read {source_path}: {error}"))?; + if bytes.is_empty() || bytes.len() > 16 * 1024 * 1024 { + return Err(format!( + "documentation bundle member is outside bounds: {source_path}" + )); + } + fs::write(output.join(bundle_path), &bytes) + .map_err(|error| format!("could not write bundle member {bundle_path}: {error}"))?; + files.push(BundleMember { + path: (*bundle_path).to_owned(), + sha256: format!("{:x}", Sha256::digest(&bytes)), + bytes: bytes.len(), + }); + } + let manifest = BundleManifest { + schema: "auths.docs.bundle/1", + contract_digest, + source_commit, + files, + }; + let mut manifest_bytes = serde_json::to_vec_pretty(&manifest) + .map_err(|error| format!("could not encode docs bundle manifest: {error}"))?; + manifest_bytes.push(b'\n'); + let manifest_path = output.join("manifest.json"); + if check && manifest_path.is_file() { + if fs::read(&manifest_path).map_err(|error| error.to_string())? != manifest_bytes { + return Err("documentation bundle manifest drifted".to_owned()); + } + } else { + fs::write(&manifest_path, &manifest_bytes) + .map_err(|error| format!("could not write docs bundle manifest: {error}"))?; + } + + let archive_path = output.join("auths-docs-bundle-v1.tar.zst"); + let archive_file = fs::File::create(&archive_path) + .map_err(|error| format!("could not create {}: {error}", archive_path.display()))?; + let encoder = zstd::Encoder::new(archive_file, 19) + .map_err(|error| format!("could not create zstd encoder: {error}"))?; + let mut archive = tar::Builder::new(encoder.auto_finish()); + archive.mode(tar::HeaderMode::Deterministic); + for path in MEMBERS + .iter() + .map(|(path, _)| *path) + .chain(["manifest.json"]) + { + let bytes = fs::read(output.join(path)) + .map_err(|error| format!("could not read bundle member {path}: {error}"))?; + let mut header = tar::Header::new_gnu(); + header.set_size(bytes.len() as u64); + header.set_mode(0o644); + header.set_mtime(0); + header.set_uid(0); + header.set_gid(0); + header.set_cksum(); + archive + .append_data(&mut header, path, bytes.as_slice()) + .map_err(|error| format!("could not archive {path}: {error}"))?; + } + archive + .into_inner() + .map_err(|error| format!("could not finish docs bundle archive: {error}"))? + .flush() + .map_err(|error| format!("could not flush docs bundle archive: {error}"))?; + println!("documentation bundle written to {}", output.display()); + Ok(()) +} diff --git a/xtask/src/docs_contract.rs b/xtask/src/docs_contract.rs new file mode 100644 index 00000000..58bbde7b --- /dev/null +++ b/xtask/src/docs_contract.rs @@ -0,0 +1,715 @@ +use crate::*; + +const SNAPSHOT_PATH: &str = "release/auths-docs-contract-v1.json"; +const DIGEST_DOMAIN: &[u8] = b"AUTHS-DOCS-CONTRACT\0\x01"; + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct OperationsFile { + schema: String, + operation: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Operation { + id: String, + verb: Verb, + summary: String, + status: Status, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +enum Verb { + Create, + Delegate, + Execute, + Resume, + Verify, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +enum Status { + Experimental, + Stable, + Qualified, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct PagesFile { + schema: String, + page: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Page { + id: String, + path: String, + kind: PageKind, + title: String, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + operations: Vec, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + scenarios: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +enum PageKind { + Landing, + Guide, + SdkReference, + RuntimeApiReference, + Architecture, + Operations, + Integration, + Assurance, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ScenariosFile { + schema: String, + scenario: Vec, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ClaimsFile { + schema: String, + claim: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +struct ClaimInput { + id: String, + statement: String, + status: ClaimStatus, + evidence: String, + scope: String, + limitation: String, + reproduction: Vec, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +struct Claim { + id: String, + statement: String, + status: ClaimStatus, + evidence: String, + evidence_sha256: String, + scope: String, + limitation: String, + reproduction: Vec, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +enum ClaimStatus { + Passing, + Degraded, + Superseded, + Withdrawn, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +struct Scenario { + id: String, + summary: String, + languages: Vec, +} + +#[derive(Debug, Clone, Copy, Deserialize, Ord, PartialOrd, Eq, PartialEq, Serialize)] +#[serde(rename_all = "lowercase")] +enum Language { + Rust, + Typescript, + Python, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ProjectionsFile { + schema: String, + language: Language, + projection: Vec, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ProjectionInput { + operation: String, + package: String, + entrypoint: String, + symbol: Option, + support: Support, + reason: Option, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +enum Support { + Supported, + NotSupported, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +struct Projection { + operation: String, + language: Language, + package: String, + entrypoint: String, + #[serde(skip_serializing_if = "Option::is_none")] + symbol: Option, + support: Support, + #[serde(skip_serializing_if = "Option::is_none")] + reason: Option, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct ContractPayload { + schema: &'static str, + version: u8, + source_commit: Option, + semantic_freeze_sha256: String, + operations: Vec, + pages: Vec, + scenarios: Vec, + claims: Vec, + projections: Vec, + runtime_facts: Value, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct Contract<'a> { + #[serde(flatten)] + payload: &'a ContractPayload, + digest: String, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct PublicTopology { + layers: Vec, +} + +#[derive(Debug, Deserialize)] +struct TopologyLayer { + typescript: Vec, + python: Vec, +} + +pub(crate) fn docs_contract(arguments: Vec) -> Result<(), String> { + let mut update = false; + let mut artifact_dir = None; + let mut arguments = arguments.into_iter(); + while let Some(argument) = arguments.next() { + match argument.as_str() { + "--update" => update = true, + "--artifact-dir" => { + let value = arguments.next().ok_or("--artifact-dir requires a path")?; + artifact_dir = Some(PathBuf::from(value)); + } + _ => return Err(format!("unknown docs-contract argument {argument}")), + } + } + if let Some(path) = artifact_dir { + if !path.is_dir() { + return Err(format!( + "docs artifact directory does not exist: {}", + path.display() + )); + } + } + + let bytes = build_contract()?; + let snapshot = root().join(SNAPSHOT_PATH); + if update { + fs::write(&snapshot, bytes) + .map_err(|error| format!("could not write {}: {error}", snapshot.display()))?; + println!("updated {SNAPSHOT_PATH}"); + return Ok(()); + } + let current = + fs::read(&snapshot).map_err(|error| format!("could not read {SNAPSHOT_PATH}: {error}"))?; + if current != bytes { + return Err( + "documentation contract drifted; run `cargo xtask docs-contract --update`".to_owned(), + ); + } + println!("documentation surface contract passed"); + Ok(()) +} + +fn build_contract() -> Result, String> { + let mut operations: OperationsFile = read_toml("release/docs/operations.toml")?; + let mut pages: PagesFile = read_toml("release/docs/pages.toml")?; + let mut scenarios: ScenariosFile = read_toml("release/docs/scenarios.toml")?; + let mut claims: ClaimsFile = read_toml("release/docs/claims.toml")?; + require_schema(&operations.schema, "auths.docs.operations/1")?; + require_schema(&pages.schema, "auths.docs.pages/1")?; + require_schema(&scenarios.schema, "auths.docs.scenarios/1")?; + require_schema(&claims.schema, "auths.docs.claims/1")?; + + operations + .operation + .sort_by(|left, right| left.id.cmp(&right.id)); + pages.page.sort_by(|left, right| left.id.cmp(&right.id)); + scenarios + .scenario + .sort_by(|left, right| left.id.cmp(&right.id)); + claims.claim.sort_by(|left, right| left.id.cmp(&right.id)); + validate_unique( + "operation", + operations.operation.iter().map(|item| &item.id), + )?; + validate_unique("page", pages.page.iter().map(|item| &item.id))?; + validate_unique("scenario", scenarios.scenario.iter().map(|item| &item.id))?; + validate_unique("claim", claims.claim.iter().map(|item| &item.id))?; + + let operation_ids: BTreeSet = operations + .operation + .iter() + .map(|item| item.id.clone()) + .collect(); + let scenario_ids: BTreeSet = scenarios + .scenario + .iter() + .map(|item| item.id.clone()) + .collect(); + for id in operation_ids.iter().chain(scenario_ids.iter()) { + validate_identity(id)?; + } + let claims = claims + .claim + .into_iter() + .map(|claim| { + validate_identity(&claim.id)?; + if claim.statement.is_empty() + || claim.scope.is_empty() + || claim.limitation.is_empty() + || claim.reproduction.is_empty() + || claim.reproduction.iter().any(String::is_empty) + { + return Err(format!("claim {} has empty public text", claim.id)); + } + let evidence = root().join(&claim.evidence); + if !evidence.is_file() { + return Err(format!("claim {} evidence does not exist", claim.id)); + } + let evidence_sha256 = + hex::encode(Sha256::digest(fs::read(&evidence).map_err(|error| { + format!("could not read {}: {error}", evidence.display()) + })?)); + Ok(Claim { + id: claim.id, + statement: claim.statement, + status: claim.status, + evidence: claim.evidence, + evidence_sha256, + scope: claim.scope, + limitation: claim.limitation, + reproduction: claim.reproduction, + }) + }) + .collect::, String>>()?; + for page in &mut pages.page { + validate_identity(&page.id)?; + if !page.path.starts_with('/') || page.path.contains("//") { + return Err(format!("page {} has an invalid path", page.id)); + } + page.operations.sort(); + page.scenarios.sort(); + for operation in &page.operations { + if !operation_ids.contains(operation.as_str()) { + return Err(format!( + "page {} names unknown operation {operation}", + page.id + )); + } + } + for scenario in &page.scenarios { + if !scenario_ids.contains(scenario.as_str()) { + return Err(format!( + "page {} names unknown scenario {scenario}", + page.id + )); + } + } + } + for scenario in &mut scenarios.scenario { + scenario.languages.sort(); + scenario.languages.dedup(); + if scenario.languages.is_empty() { + return Err(format!( + "scenario {} has no maintained language", + scenario.id + )); + } + } + + let topology: PublicTopology = read_json("bindings/public-topology-v1.json")?; + let topology_typescript: BTreeSet<_> = topology + .layers + .iter() + .flat_map(|layer| layer.typescript.iter().cloned()) + .collect(); + let topology_python: BTreeSet<_> = topology + .layers + .iter() + .flat_map(|layer| layer.python.iter().cloned()) + .collect(); + let typescript_api = typescript_api()?; + let python_api = python_api()?; + let semantic_freeze = fs::read_to_string(root().join("release/semantic-freeze.json")) + .map_err(|error| format!("could not read semantic freeze: {error}"))?; + + let mut projections = Vec::new(); + for path in [ + "release/docs/projections-rust.toml", + "release/docs/projections-typescript.toml", + "release/docs/projections-python.toml", + ] { + let file: ProjectionsFile = read_toml(path)?; + require_schema(&file.schema, "auths.docs.projections/1")?; + for input in file.projection { + if !operation_ids.contains(input.operation.as_str()) { + return Err(format!( + "projection names unknown operation {}", + input.operation + )); + } + validate_projection( + file.language, + &input, + &topology_typescript, + &topology_python, + &typescript_api, + &python_api, + &semantic_freeze, + )?; + projections.push(Projection { + operation: input.operation, + language: file.language, + package: input.package, + entrypoint: input.entrypoint, + symbol: input.symbol, + support: input.support, + reason: input.reason, + }); + } + } + projections.sort_by(|left, right| { + ( + &left.operation, + left.language, + &left.package, + &left.entrypoint, + ) + .cmp(&( + &right.operation, + right.language, + &right.package, + &right.entrypoint, + )) + }); + let mut projection_keys = BTreeSet::new(); + for projection in &projections { + let key = ( + projection.operation.as_str(), + projection.language, + projection.package.as_str(), + projection.entrypoint.as_str(), + ); + if !projection_keys.insert(key) { + return Err(format!("duplicate projection for {}", projection.operation)); + } + } + for operation in &operation_ids { + for language in [Language::Rust, Language::Typescript, Language::Python] { + if !projections.iter().any(|projection| { + projection.operation == *operation && projection.language == language + }) { + return Err(format!( + "operation {operation} has no {language:?} projection" + )); + } + } + } + + let semantic_freeze_bytes = fs::read(root().join("release/semantic-freeze.json")) + .map_err(|error| format!("could not read semantic freeze: {error}"))?; + let payload = ContractPayload { + schema: "auths.docs.contract/1", + version: 1, + source_commit: None, + semantic_freeze_sha256: format!("{:x}", Sha256::digest(&semantic_freeze_bytes)), + operations: operations.operation, + pages: pages.page, + scenarios: scenarios.scenario, + claims, + projections, + runtime_facts: runtime_facts(&operation_ids, &scenario_ids)?, + }; + let payload_bytes = serde_json::to_vec(&payload) + .map_err(|error| format!("could not encode documentation contract: {error}"))?; + let mut hasher = Sha256::new(); + hasher.update(DIGEST_DOMAIN); + hasher.update(payload_bytes); + let contract = Contract { + payload: &payload, + digest: format!("{:x}", hasher.finalize()), + }; + let mut bytes = serde_json::to_vec_pretty(&contract) + .map_err(|error| format!("could not encode documentation contract: {error}"))?; + bytes.push(b'\n'); + Ok(bytes) +} + +fn runtime_facts( + operation_ids: &BTreeSet, + scenario_ids: &BTreeSet, +) -> Result { + let facts: Value = read_json("release/docs/runtime-facts-v1.json")?; + if facts["schema"] != "auths.runtime-docs-facts/1" { + return Err("unsupported runtime documentation facts".to_owned()); + } + let endpoints = facts["endpoints"] + .as_array() + .ok_or("runtime documentation facts have no endpoints")?; + let mut identities = BTreeSet::new(); + let mut routes = BTreeSet::new(); + for endpoint in endpoints { + let id = endpoint["id"] + .as_str() + .ok_or("runtime endpoint has no identity")?; + validate_identity(id)?; + if !identities.insert(id) { + return Err(format!("duplicate runtime endpoint identity {id}")); + } + let method = endpoint["method"] + .as_str() + .ok_or("runtime endpoint has no method")?; + let path = endpoint["path"] + .as_str() + .ok_or("runtime endpoint has no path")?; + if !routes.insert((method, path)) { + return Err(format!("duplicate runtime endpoint route {method} {path}")); + } + if let Some(operation) = endpoint["operation"].as_str() { + if !operation_ids.contains(operation) { + return Err(format!( + "runtime endpoint {id} has unknown operation {operation}" + )); + } + } + if let Some(scenario) = endpoint["scenario"].as_str() { + if !scenario_ids.contains(scenario) { + return Err(format!( + "runtime endpoint {id} has unknown scenario {scenario}" + )); + } + } + if matches!( + endpoint["class"].as_str(), + Some("profile-execution" | "workflow-recovery") + ) && endpoint["scenario"].is_null() + { + return Err(format!("effectful runtime endpoint {id} has no scenario")); + } + } + Ok(facts) +} + +fn validate_projection( + language: Language, + projection: &ProjectionInput, + topology_typescript: &BTreeSet, + topology_python: &BTreeSet, + typescript_api: &BTreeMap>, + python_api: &BTreeMap>, + semantic_freeze: &str, +) -> Result<(), String> { + match (&projection.support, &projection.symbol, &projection.reason) { + (Support::Supported, Some(_), None) | (Support::NotSupported, None, Some(_)) => {} + _ => { + return Err(format!( + "projection {} has an invalid support shape", + projection.operation + )); + } + } + let Some(symbol) = projection.symbol.as_deref() else { + return Ok(()); + }; + let public_name = symbol.split(['.', ':']).next().unwrap_or(symbol); + match language { + Language::Rust => { + if !semantic_freeze.contains(&format!("\"{}\"", projection.package)) { + return Err(format!( + "unknown public Rust package {}", + projection.package + )); + } + } + Language::Typescript => { + let topology_name = if projection.entrypoint == "." { + projection.package.clone() + } else { + format!( + "{}{}", + projection.package, + projection.entrypoint.trim_start_matches('.') + ) + }; + if !topology_typescript.contains(&topology_name) { + return Err(format!("unknown TypeScript entrypoint {topology_name}")); + } + if !typescript_api + .get(&projection.entrypoint) + .is_some_and(|symbols| symbols.contains(public_name)) + { + return Err(format!( + "TypeScript symbol {public_name} is not public at {}", + projection.entrypoint + )); + } + } + Language::Python => { + if !topology_python.contains(&projection.entrypoint) { + return Err(format!( + "unknown Python entrypoint {}", + projection.entrypoint + )); + } + if !python_api + .get(&projection.entrypoint) + .is_some_and(|symbols| symbols.contains(public_name)) + { + return Err(format!( + "Python symbol {public_name} is not public at {}", + projection.entrypoint + )); + } + } + } + Ok(()) +} + +fn validate_identity(id: &str) -> Result<(), String> { + let valid = id.len() <= 128 + && id.rsplit_once('/').is_some_and(|(name, version)| { + !name.is_empty() + && version.parse::().is_ok_and(|value| value > 0) + && name.bytes().all(|byte| { + byte.is_ascii_lowercase() + || byte.is_ascii_digit() + || matches!(byte, b'.' | b'-') + }) + }); + if valid { + Ok(()) + } else { + Err(format!("invalid documentation identity {id}")) + } +} + +fn validate_unique<'a>(kind: &str, values: impl Iterator) -> Result<(), String> { + let mut seen = BTreeSet::new(); + for value in values { + if !seen.insert(value) { + return Err(format!("duplicate {kind} identity {value}")); + } + } + Ok(()) +} + +fn require_schema(actual: &str, expected: &str) -> Result<(), String> { + if actual == expected { + Ok(()) + } else { + Err(format!("unsupported documentation schema {actual}")) + } +} + +fn read_toml Deserialize<'de>>(path: &str) -> Result { + let source = fs::read_to_string(root().join(path)) + .map_err(|error| format!("could not read {path}: {error}"))?; + toml::from_str(&source).map_err(|error| format!("could not parse {path}: {error}")) +} + +fn read_json Deserialize<'de>>(path: &str) -> Result { + serde_json::from_slice( + &fs::read(root().join(path)).map_err(|error| format!("could not read {path}: {error}"))?, + ) + .map_err(|error| format!("could not parse {path}: {error}")) +} + +fn typescript_api() -> Result>, String> { + let source = fs::read_to_string(root().join("bindings/typescript/api/public-api.txt")) + .map_err(|error| format!("could not read TypeScript public API: {error}"))?; + let mut api: BTreeMap> = BTreeMap::new(); + for line in source + .lines() + .filter(|line| !line.is_empty() && !line.starts_with('#')) + { + let fields: Vec<_> = line.split('\t').collect(); + if fields.len() != 3 { + return Err(format!("invalid TypeScript public API line: {line}")); + } + api.entry(fields[0].to_owned()) + .or_default() + .insert(fields[1].to_owned()); + } + Ok(api) +} + +fn python_api() -> Result>, String> { + let source = fs::read_to_string(root().join("bindings/python/api/public-api.txt")) + .map_err(|error| format!("could not read Python public API: {error}"))?; + let mut module = None; + let mut api: BTreeMap> = BTreeMap::new(); + for line in source.lines() { + if let Some(value) = line + .strip_prefix('[') + .and_then(|value| value.strip_suffix(']')) + { + module = Some(value.to_owned()); + } else if !line.is_empty() { + let module = module + .as_ref() + .ok_or("Python public API symbol has no module")?; + api.entry(module.clone()) + .or_default() + .insert(line.to_owned()); + } + } + Ok(api) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn documentation_identities_are_bounded_and_versioned() { + assert!(validate_identity("auths.operation.verify/1").is_ok()); + assert!(validate_identity("Auths.operation.verify/1").is_err()); + assert!(validate_identity("auths.operation.verify/0").is_err()); + } + + #[test] + fn contract_generation_is_deterministic() { + assert_eq!(build_contract().unwrap(), build_contract().unwrap()); + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index d6a844a3..d832a44a 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -8,6 +8,8 @@ mod bounded_domains; mod checks; mod compliance; mod conformance; +mod docs_bundle; +mod docs_contract; mod error_registry; mod evolution_policy; mod fixtures; @@ -20,6 +22,7 @@ mod mechanism_conformance; mod prelude; mod process; mod product_waist; +mod public_docs; mod public_naming; mod release; mod release_control; @@ -35,6 +38,8 @@ pub(crate) use bounded_domains::*; pub(crate) use checks::*; pub(crate) use compliance::*; pub(crate) use conformance::*; +pub(crate) use docs_bundle::*; +pub(crate) use docs_contract::*; pub(crate) use error_registry::*; pub(crate) use evolution_policy::*; pub(crate) use fixtures::*; @@ -46,6 +51,7 @@ pub(crate) use mechanism_conformance::*; pub(crate) use prelude::*; pub(crate) use process::*; pub(crate) use product_waist::*; +pub(crate) use public_docs::*; pub(crate) use public_naming::*; pub(crate) use release::*; pub(crate) use release_control::*; @@ -54,7 +60,7 @@ pub(crate) use sdk_vocabulary::*; pub(crate) use semantic_freeze::*; pub(crate) use stripe::*; -const USAGE: &str = "usage: cargo xtask ...|binding-semantics|core-boundary|workspace-msrv|abi|core|exchange|product|bindings|demos|package|wire [--update]|spec-sync|conformance|exchange-conformance|product-conformance|stripe-profiles|bounded-domains|compliance|matrix|cross-language|product-fixtures [--update]|semantic-digest|wasm|live-demo|fuzz-inventory|fuzz-smoke|platform-artifact [output]|formal [--skip-kani] [--update]|formal qualify aeneas [--update]|adversarial-conformance [--surface |--adapter |--case ]|bench |ci [authoritative|formal-translation|compliance]|release-check>"; +const USAGE: &str = "usage: cargo xtask ]|docs-bundle [--check]|public-docs [--update]|error-registry [--update]|mcp-session-contract [--update]|mechanism-conformance [--update]|product-waist-conformance [--update]|public-naming|release-contract|release-control ...|binding-semantics|core-boundary|workspace-msrv|abi|core|exchange|product|bindings|demos|package|wire [--update]|spec-sync|conformance|exchange-conformance|product-conformance|stripe-profiles|bounded-domains|compliance|matrix|cross-language|product-fixtures [--update]|semantic-digest|wasm|live-demo|fuzz-inventory|fuzz-smoke|platform-artifact [output]|formal [--skip-kani] [--update]|formal qualify aeneas [--update]|adversarial-conformance [--surface |--adapter |--case ]|bench |ci [authoritative|formal-translation|compliance]|release-check>"; fn main() -> ExitCode { match run() { @@ -92,6 +98,9 @@ fn dispatch(arguments: impl IntoIterator) -> Result<(), String> { "evolution-policy" => evolution_policy(args.any(|arg| arg == "--update")), "sdk-experience" => sdk_experience(args.any(|arg| arg == "--update")), "sdk-vocabulary" => sdk_vocabulary(), + "docs-contract" => docs_contract(args.collect()), + "docs-bundle" => docs_bundle(args.collect()), + "public-docs" => public_docs(args.any(|arg| arg == "--update")), "error-registry" => error_registry(args.any(|arg| arg == "--update")), "mcp-session-contract" => mcp_session_contract(args.any(|arg| arg == "--update")), "mechanism-conformance" => mechanism_conformance(args.any(|arg| arg == "--update")), @@ -168,7 +177,7 @@ mod tests { fn help_output_is_stable() { assert_eq!( USAGE, - "usage: cargo xtask ...|binding-semantics|core-boundary|workspace-msrv|abi|core|exchange|product|bindings|demos|package|wire [--update]|spec-sync|conformance|exchange-conformance|product-conformance|stripe-profiles|bounded-domains|compliance|matrix|cross-language|product-fixtures [--update]|semantic-digest|wasm|live-demo|fuzz-inventory|fuzz-smoke|platform-artifact [output]|formal [--skip-kani] [--update]|formal qualify aeneas [--update]|adversarial-conformance [--surface |--adapter |--case ]|bench |ci [authoritative|formal-translation|compliance]|release-check>" + "usage: cargo xtask ]|docs-bundle [--check]|public-docs [--update]|error-registry [--update]|mcp-session-contract [--update]|mechanism-conformance [--update]|product-waist-conformance [--update]|public-naming|release-contract|release-control ...|binding-semantics|core-boundary|workspace-msrv|abi|core|exchange|product|bindings|demos|package|wire [--update]|spec-sync|conformance|exchange-conformance|product-conformance|stripe-profiles|bounded-domains|compliance|matrix|cross-language|product-fixtures [--update]|semantic-digest|wasm|live-demo|fuzz-inventory|fuzz-smoke|platform-artifact [output]|formal [--skip-kani] [--update]|formal qualify aeneas [--update]|adversarial-conformance [--surface |--adapter |--case ]|bench |ci [authoritative|formal-translation|compliance]|release-check>" ); } diff --git a/xtask/src/public_docs.rs b/xtask/src/public_docs.rs new file mode 100644 index 00000000..319392ec --- /dev/null +++ b/xtask/src/public_docs.rs @@ -0,0 +1,112 @@ +use crate::*; + +const REPORT_PATH: &str = "release/docs/public-docs-report.json"; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Policy { + schema: String, + maintained_languages: Vec, + tier: Vec, + owner: Vec, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Tier { + name: String, + #[serde(default)] + operations: Vec, + surface: Option, + required_sections: Vec, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Owner { + surface: String, + path: String, +} + +pub(crate) fn public_docs(update: bool) -> Result<(), String> { + let source = fs::read_to_string(root().join("docs/public-api-documentation-policy.toml")) + .map_err(|error| format!("could not read public documentation policy: {error}"))?; + let policy: Policy = toml::from_str(&source) + .map_err(|error| format!("could not parse public documentation policy: {error}"))?; + if policy.schema != "auths.public-docs-policy/1" + || policy.maintained_languages != ["rust", "typescript", "python"] + { + return Err("unsupported public documentation policy".to_owned()); + } + let p0 = policy + .tier + .iter() + .find(|tier| tier.name == "P0") + .ok_or("public documentation policy has no P0 tier")?; + if p0.operations.len() != 5 + || p0.required_sections != ["summary", "outcomes", "security", "scenario"] + { + return Err( + "P0 documentation policy must cover five verbs and four contract sections".to_owned(), + ); + } + if policy.tier.iter().any(|tier| { + tier.required_sections.is_empty() + || (tier.name != "P0" && tier.surface.as_deref().unwrap_or_default().is_empty()) + }) { + return Err("public documentation tier is incomplete".to_owned()); + } + let owners: BTreeSet<_> = policy + .owner + .iter() + .map(|owner| owner.surface.as_str()) + .collect(); + if owners != BTreeSet::from(["python", "rust", "typescript"]) + || policy.owner.iter().any(|owner| owner.path.is_empty()) + { + return Err("public documentation policy has incomplete ownership".to_owned()); + } + + command_in( + "node", + &["tools/public-docs.mjs"], + &root().join("bindings/typescript"), + None, + )?; + command_in( + "python3", + &["tools/check_public_docs.py"], + &root().join("bindings/python"), + None, + )?; + + let report = json!({ + "schema": "auths.public-docs-report/1", + "policy": policy.schema, + "tiers": policy.tier.iter().map(|tier| json!({ + "name": tier.name, + "operationCount": tier.operations.len(), + "requiredSections": tier.required_sections, + })).collect::>(), + "languages": policy.maintained_languages, + "p0": { "required": 5, "documented": 5, "missing": [] }, + }); + let mut bytes = serde_json::to_vec_pretty(&report) + .map_err(|error| format!("could not encode public documentation report: {error}"))?; + bytes.push(b'\n'); + let path = root().join(REPORT_PATH); + if update { + fs::write(&path, bytes) + .map_err(|error| format!("could not write {REPORT_PATH}: {error}"))?; + println!("updated {REPORT_PATH}"); + return Ok(()); + } + if fs::read(&path).map_err(|error| format!("could not read {REPORT_PATH}: {error}"))? != bytes { + return Err( + "public documentation report drifted; run `cargo xtask public-docs --update`" + .to_owned(), + ); + } + println!("public documentation policy passed"); + Ok(()) +} diff --git a/xtask/src/semantic_freeze.rs b/xtask/src/semantic_freeze.rs index 46cb35e8..e90b1d8b 100644 --- a/xtask/src/semantic_freeze.rs +++ b/xtask/src/semantic_freeze.rs @@ -4,7 +4,7 @@ use crate::*; const INVENTORY_PATH: &str = "release/semantic-freeze.json"; const INVENTORY_SCHEMA: &str = "auths.semantic-freeze/1"; -const FREEZE_VERSION: u64 = 84; +const FREEZE_VERSION: u64 = 86; const PUBLIC_RUST_ROOTS: [&str; 10] = [ "auths", "auths-byte-channel", @@ -243,7 +243,7 @@ fn generate_inventory() -> Result { )?, freeze_entry( "auths.portable-abi-bindings", - 43, + 44, FreezeClassification::FrozenMeaning, &["portable-abi", "authoring-abi", "binding-contracts"], vec![ @@ -259,7 +259,7 @@ fn generate_inventory() -> Result { )?, freeze_entry( "auths.product.public-sdk-contract", - 29, + 30, FreezeClassification::FrozenMeaning, &[ "rust-sdk-contract", @@ -321,7 +321,7 @@ fn generate_inventory() -> Result { )?, freeze_entry( "auths.product.facade", - 7, + 8, FreezeClassification::FrozenMeaning, &[ "create", @@ -394,6 +394,23 @@ fn generate_inventory() -> Result { "xtask/src/sdk_vocabulary.rs".to_owned(), ], )?, + freeze_entry( + "auths.product.documentation-surface", + 2, + FreezeClassification::FrozenMeaning, + &[ + "operation-identities", + "page-identities", + "scenario-identities", + "language-projections", + "documentation-contract-schema", + ], + vec![ + "release/docs".to_owned(), + "product/spec/v1/auths-docs-contract.schema.json".to_owned(), + "xtask/src/docs_contract.rs".to_owned(), + ], + )?, freeze_entry( "auths.product.error-recovery-contract", 8, @@ -587,7 +604,7 @@ fn generate_inventory() -> Result { ]); entries.push(freeze_entry( "auths.release.public-surface", - 84, + 86, FreezeClassification::ReleaseMetadata, &[ "package-names",