Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
38eb248
docs: freeze documentation surface contract
bordumb Aug 14, 2026
48d0469
docs: enforce source-owned public API documentation
bordumb Aug 14, 2026
7faaeed
docs: export typed runtime facts
bordumb Aug 14, 2026
341c11b
docs: build immutable documentation bundle
bordumb Aug 14, 2026
57eba47
docs: qualify cross-repository documentation release
bordumb Aug 14, 2026
c3b5b21
docs: separate platform and editorial documentation lanes
bordumb Aug 14, 2026
ebd2ed8
docs: record content ownership epic completion
bordumb Aug 14, 2026
c0132ac
docs: record topic landing epic completion
bordumb Aug 14, 2026
14a05a1
docs: record getting started epic completion
bordumb Aug 14, 2026
d109bc4
docs: record semantic tour epic completion
bordumb Aug 14, 2026
fbc50c2
docs: define qualified quickstart scenarios
bordumb Aug 14, 2026
2c369e9
docs: record developer reference epic completion
bordumb Aug 14, 2026
fc84651
docs: record agent integration epic completion
bordumb Aug 14, 2026
957d532
docs: record adoption epic completion
bordumb Aug 14, 2026
bc65c96
docs: record operations epic completion
bordumb Aug 14, 2026
efd2cac
docs: audit content hierarchy and replan navigation
bordumb Aug 14, 2026
ca69e41
docs: complete canonical information architecture epic
bordumb Aug 14, 2026
23766f9
docs: complete topic shell epic
bordumb Aug 14, 2026
0c778de
docs: complete executable get started epic
bordumb Aug 14, 2026
8c9462e
docs: complete identity and trust epic
bordumb Aug 14, 2026
da22877
docs: complete authority content epic
bordumb Aug 14, 2026
acff73d
docs: complete agents and MCP content epic
bordumb Aug 14, 2026
3d4eeef
docs: complete production operations content epic
bordumb Aug 14, 2026
91afd87
docs: complete developer content epic
bordumb Aug 14, 2026
8c3d64d
docs: publish release-scoped assurance claims
bordumb Aug 14, 2026
d0e4a53
docs: complete full-site qualification epic
bordumb Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -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"
45 changes: 45 additions & 0 deletions bindings/python/python/auths/_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(
Expand Down Expand Up @@ -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:
Expand All @@ -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(
Expand All @@ -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)
Expand Down
35 changes: 35 additions & 0 deletions bindings/python/tools/check_public_docs.py
Original file line number Diff line number Diff line change
@@ -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()
25 changes: 25 additions & 0 deletions bindings/python/tools/docs_surface.py
Original file line number Diff line number Diff line change
@@ -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()
11 changes: 11 additions & 0 deletions bindings/typescript/api/tsdoc.json
Original file line number Diff line number Diff line change
@@ -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
}
}
27 changes: 27 additions & 0 deletions bindings/typescript/src/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -139,6 +146,12 @@ export interface Auths {
provider: McpClosedProvider;
requestId?: string;
}>): Promise<PlanExecutionResult>;
/**
* 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;
Expand All @@ -148,6 +161,13 @@ export interface Auths {
provider: McpClosedProvider;
requestId?: string;
}>): Promise<SingleExecutionResult>;
/**
* 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;
Expand Down Expand Up @@ -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<Auths> {
const resources = configurationResources.get(configuration);
if (resources === undefined) throw new TypeError("Auths configuration was not created by an integration");
Expand Down
17 changes: 17 additions & 0 deletions bindings/typescript/tools/docs-surface.mjs
Original file line number Diff line number Diff line change
@@ -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`);
19 changes: 19 additions & 0 deletions bindings/typescript/tools/public-docs.mjs
Original file line number Diff line number Diff line change
@@ -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: [] }));
29 changes: 29 additions & 0 deletions docs/public-api-documentation-policy.toml
Original file line number Diff line number Diff line change
@@ -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"
Loading