{"openapi":"3.1.0","info":{"title":"a4sx","version":"0.1.0"},"paths":{"/healthz":{"get":{"summary":"Healthz","description":"Liveness probe. 200 while the process is alive — INCLUDING during the\nbackground startup warmup (the pod is healthy, just not yet ready for data;\nsee specs/nonblocking-startup/v0.1.md). Returns 503 only when the warmup\nhas FATALLY failed, so k8s restarts the pod instead of leaving it\npermanently un-ready. Backward-compatible: `ok` is always present; `version`\n/ `spec_version` are additive.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/status":{"get":{"summary":"Status Page","description":"A tiny PUBLIC status view (WP-23): is the site serving, is it ready for data, which\nversion runs. Built from the same fields as /healthz and nothing else — no counts, no\ncapacity, no internals. A browser gets a readable page; anything else gets JSON. Always\n200 (the page reports the state; a monitor that wants a failing probe uses /healthz).","operationId":"status_page_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/readyz":{"get":{"summary":"Readyz","description":"Readiness. Anonymous: `{\"ok\": true}` (200) or `{\"ok\": false, \"reason\"}` (503 — the reason\nis the same `ready_reason` the public /healthz already shows). With a platform credential — a\nglobal admin, or a valid read / emit / admin token or member session of the default tenant —\nthe 200 body adds `data_dir`, `events_count`, `events_count_age_s`, `capacity` and\n`ignored_events` (the fold's refusal counters; the per-producer module breakdown only for a\nglobal admin)\n(RR01-SEC-C04, RR03-SEC-10: host capacity and platform event volume are not public, and not\na workspace's business either). Any other credential gets `{\"ok\": true}`.","operationId":"readyz_readyz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/version":{"get":{"summary":"Version","description":"Running build + advertised capabilities. See module docstring for sources.\n`git_sha`/`built_at` appear only when injected; `links` point at live\ndiscovery surfaces (`/releases` is added once the release feed ships).","operationId":"version_version_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Version Version Get"}}}}}}},"/auth/whoami":{"get":{"summary":"Whoami","description":"Confirm the bearer token is valid and say who it belongs to.\n\n200 with the caller's identity, or 401. Accepts read OR emit tokens (same gate as the data\nroutes a caller is proving access for), and rejects admin/registration — so nothing is tempted\nto use an admin credential for a routine liveness check.\n\nResolution is tenant-local first (by Host). On a 401 miss, a UNIFIED `ge_tok_` is resolved\nACROSS tenants (see `_resolve_cross_tenant_unified`) so the fleet router — which probes the\ndefault collector base first — learns the token's owning tenant from that one probe, with no\nper-tenant routes.json entry. The `x-polaris-tenant` response header (set by the tenant\nmiddleware from `request.state.tenant_id`, which the fallback overrides) names that owner.","operationId":"whoami_auth_whoami_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Whoami Auth Whoami Get"}}}}}}},"/cli/{name}":{"get":{"summary":"Cli File","operationId":"cli_file_cli__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/install.sh":{"get":{"summary":"Install Sh","operationId":"install_sh_install_sh_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/releases":{"get":{"summary":"List Releases","operationId":"list_releases_releases_get","parameters":[{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"filter to one channel, e.g. stable","title":"Channel"},"description":"filter to one channel, e.g. stable"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"version (semver) or ISO timestamp; returns strictly newer","title":"Since"},"description":"version (semver) or ISO timestamp; returns strictly newer"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"keyset cursor — the `version` of the previous page's last item","title":"Cursor"},"description":"keyset cursor — the `version` of the previous page's last item"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Releases Releases Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/releases/latest":{"get":{"summary":"Latest Release","operationId":"latest_release_releases_latest_get","parameters":[{"name":"channel","in":"query","required":false,"schema":{"type":"string","default":"stable","title":"Channel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Latest Release Releases Latest Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/releases.atom":{"get":{"summary":"Releases Atom","description":"Atom 1.0 feed — drops straight into feed readers / a chat webhook.","operationId":"releases_atom_releases_atom_get","parameters":[{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/releases/{version}":{"get":{"summary":"Get Release","operationId":"get_release_releases__version__get","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Release Releases  Version  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events":{"post":{"summary":"Post Event","operationId":"post_event_events_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"get":{"summary":"List Events","operationId":"list_events_events_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Until"}},{"name":"repository","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository"}},{"name":"pr","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pr"}},{"name":"correlation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correlation Id"}},{"name":"ticket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"}},{"name":"epic","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Epic"}},{"name":"producer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Producer Id"}},{"name":"actor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Id"}},{"name":"run_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Id"}},{"name":"station","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Station"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type"}},{"name":"role","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","default":"timestamp","title":"Order"}},{"name":"descending","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Descending"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/quarantine/summary":{"get":{"summary":"Quarantine Summary","description":"Quarantine aggregate for the Attention view: events the collector STORED but\ntagged (unknown repository / inactive station) — they are kept in the log and\nhidden from projections until the cause is fixed. Ingest rejections (schema, auth)\nare not stored and are not counted here.","operationId":"quarantine_summary_events_quarantine_summary_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Quarantine Summary Events Quarantine Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/sse":{"get":{"summary":"Stream Events Sse","operationId":"stream_events_sse_events_sse_get","parameters":[{"name":"last_event_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/spec/envelope.schema.json":{"get":{"summary":"Get Envelope Schema","operationId":"get_envelope_schema_spec_envelope_schema_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/spec/SPEC.md":{"get":{"summary":"Get Spec Md","operationId":"get_spec_md_spec_SPEC_md_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/spec":{"get":{"summary":"Get Spec Index","operationId":"get_spec_index_spec_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Spec Index Spec Get"}}}}}}},"/producers/register":{"post":{"summary":"Register Producer","operationId":"register_producer_producers_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProducerRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/approve":{"post":{"summary":"Approve Producer","operationId":"approve_producer_producers__producer_id__approve_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProducerApproveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/reject":{"post":{"summary":"Reject Producer","operationId":"reject_producer_producers__producer_id__reject_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProducerRejectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/token":{"get":{"summary":"Collect Emitter Token","operationId":"collect_emitter_token_producers__producer_id__token_get","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers":{"get":{"summary":"List Producers","operationId":"list_producers_producers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/producers/{producer_id}":{"get":{"summary":"Get Producer","operationId":"get_producer_producers__producer_id__get","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/revoke":{"post":{"summary":"Revoke Producer","operationId":"revoke_producer_producers__producer_id__revoke_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/tokens":{"post":{"summary":"Mint Emitter Token","description":"Mint an additional emitter token for an already-approved producer.\n\nMultiple emitter tokens per producer is the supported pattern for\nmulti-instance agents (e.g. several runners of the same skill). All\ntokens for the producer attribute events to the same producer name;\nthey differ by `producer.run_id` / `producer.host` set on each emit.","operationId":"mint_emitter_token_producers__producer_id__tokens_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Emitter Tokens","operationId":"list_emitter_tokens_producers__producer_id__tokens_get","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/tokens/{token_id}/revoke":{"post":{"summary":"Revoke Emitter Token","operationId":"revoke_emitter_token_producers__producer_id__tokens__token_id__revoke_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}},{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/roles":{"post":{"summary":"Assign Producer Role","operationId":"assign_producer_role_producers__producer_id__roles_post","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProducerRoleAssignRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/producers/{producer_id}/roles/{role}":{"delete":{"summary":"Remove Producer Role","operationId":"remove_producer_role_producers__producer_id__roles__role__delete","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}},{"name":"role","in":"path","required":true,"schema":{"type":"string","title":"Role"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/repositories":{"get":{"summary":"List Repositories","operationId":"list_repositories_repositories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Repository","operationId":"register_repository_repositories_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stations":{"get":{"summary":"List Stations","operationId":"list_stations_stations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Station","operationId":"register_station_stations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stations/{name}/deactivate":{"post":{"summary":"Deactivate Station","operationId":"deactivate_station_stations__name__deactivate_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationDeactivateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments":{"get":{"summary":"List Environments","operationId":"list_environments_environments_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Environment","operationId":"create_environment_environments_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}":{"get":{"summary":"Get Environment","operationId":"get_environment_environments__env_id__get","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/trust":{"post":{"summary":"Set Trust","operationId":"set_trust_environments__env_id__trust_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentTrustRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/eval-oracle":{"post":{"summary":"Set Eval Oracle","description":"Register the environment's evaluation oracle for SCORE VERIFICATION\n(collector/receipts.py): the shared HMAC key (stored server-side only — every\nread path scrubs it) plus `require_receipt`. Once set, request_authorization\nverifies that a reported `score` IS the oracle's signed, measured fitness;\nwith `require_receipt` it rejects anything else. Governed/meta: the loop can\nnever see or set the key — admin only.","operationId":"set_eval_oracle_environments__env_id__eval_oracle_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentEvalOracleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/gate-enforce":{"post":{"summary":"Set Gate Enforce","description":"Per-environment STRICT at_target-gate opt-in. `legs` REPLACES the env's own\nenforced-leg set — a leg listed here makes that gate hard for THIS environment\neven when the tenant-wide MODEL_GATE_ENFORCE doesn't list it (per-env can only\nADD enforcement; it never relaxes a tenant-wide gate). Governed/meta: admin only\n— a loop can never opt its own env into (or out of) strict grading. Empty list\nclears the env's enforcement.","operationId":"set_gate_enforce_environments__env_id__gate_enforce_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentGateEnforceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/frontier-policy":{"post":{"summary":"Set Frontier Policy","description":"Opt an environment in/out of frontier-coverage (spec frontier-coverage/v0.1).\n\nSets `kind` (drives the expected-dimension prior) and/or `frontier_policy`\n(`distinctness_theta`, `require_probe_before_complete`,\n`external_integration_required`) on the env record — which `GET /model/{env}/\ncoverage|frontier` and the at_target gate then read. MERGE semantics at both\nlevels: only fields present in the body are changed, and within\n`frontier_policy` only the KEYS SENT are changed (a key set to null is removed,\nreverting it to its default) — so tweaking one knob can't silently drop\nanother (e.g. a theta tweak must not flip the completeness gate on). Send\n`frontier_policy: null` to opt back out wholesale to legacy\n`complete = all at_target`. Governed/meta: the loop reads this, never writes it.","operationId":"set_frontier_policy_environments__env_id__frontier_policy_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentFrontierPolicyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/deactivate":{"post":{"summary":"Deactivate Environment","description":"Retire an environment: mark its record `status=deactivated`. The default\nenvironment can't be deactivated (it owns the pre-existing stations).\n\n2e — the data plane: by default this is a record-level flag only, and the env's\nstations keep emitting (the contradiction the crypto-portfolio deactivation hit).\nPass `?cascade_stations=true` to also QUARANTINE the env's stations — reassign\nthem to an inert ``_retired:<env>`` environment so their events stop folding into\nany active env's model. Reversible: reassign a station's environment to restore it.","operationId":"deactivate_environment_environments__env_id__deactivate_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}},{"name":"cascade_stations","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Cascade Stations"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/prune-environments":{"post":{"summary":"Prune Environments","description":"DESTRUCTIVE, admin-only: permanently DELETE every event belonging to the given\nenvironments' stations, reclaiming disk that `deactivate` (a reversible flag) cannot.\nMatches stations currently IN each env OR quarantined to ``_retired:<env>`` (so it\nworks after a cascade-deactivate). The default environment can never be pruned.\nRequires ``confirm: true``.\n\nASYNC: the actual rewrite/delete can exceed the ingress timeout on a large store,\nso this validates + kicks off a BACKGROUND job and returns 202 immediately. Poll\n``GET /admin/prune-environments/status`` for progress. Entity/skill projections\n(derived from the same JSONL) reconcile on the next collector start.","operationId":"prune_environments_admin_prune_environments_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PruneEnvironmentsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/prune-environments/status":{"get":{"summary":"Prune Environments Status","description":"The latest prune job for this tenant (running/done/error + counts), or\n{state: idle} if none has run since the last restart.","operationId":"prune_environments_status_admin_prune_environments_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/legal/retention":{"get":{"summary":"Legal Retention","description":"The retention windows that actually run, next to the published policy\n(collector/retention_policy.py, quoted by the Privacy text). Unauthenticated: it is\nconfiguration the Privacy Policy already discloses, and it lets an external check\ncompare prod with the text without SSH. `matches_published` is the one-bit answer.","operationId":"legal_retention_legal_retention_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/retention/plan":{"get":{"summary":"Retention Plan","description":"GLOBAL admin, read-only: what the next retention pass WOULD delete under the effective\nwindows (counts + bytes by event type and by class: general, a per-type/prefix window, or a\nper-item class — non-legal support / mail, withdrawn AI opt-outs). Writes nothing; reads the\nwhole log, so it costs a full scan (minutes on a large log).","operationId":"retention_plan_retention_plan_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/retention/purge":{"post":{"summary":"Purge Events","operationId":"purge_events_retention_purge_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/environments/{env_id}/archive":{"post":{"summary":"Archive Environment","operationId":"archive_environment_environments__env_id__archive_post","parameters":[{"name":"env_id","in":"path","required":true,"schema":{"type":"string","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveEnvRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/retention/prune":{"post":{"summary":"Prune Events","operationId":"prune_events_retention_prune_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PruneRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/retention/archives":{"get":{"summary":"List Archives","operationId":"list_archives_retention_archives_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/retention/archives/{label}/restore":{"post":{"summary":"Restore Archive","operationId":"restore_archive_retention_archives__label__restore_post","parameters":[{"name":"label","in":"path","required":true,"schema":{"type":"string","title":"Label"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/retention/archives/{label}/delete":{"post":{"summary":"Delete Archive","description":"IRREVERSIBLE hard-delete of a cold archive. `confirm` must equal the label\n(the GitHub delete-repo gesture).","operationId":"delete_archive_retention_archives__label__delete_post","parameters":[{"name":"label","in":"path","required":true,"schema":{"type":"string","title":"Label"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteConfirm"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/specs":{"get":{"summary":"List Fleet Specs","operationId":"list_fleet_specs_fleet_specs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Fleet Spec","operationId":"register_fleet_spec_fleet_specs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetSpecRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/specs/all":{"get":{"summary":"List All Fleet Specs","description":"Cross-tenant fleet enumeration (specs/multi-tenancy/v0.1 Phase 4) — the\nexecutor's full-fleet source of truth. GLOBAL admin only: a normal tenant read\nonly ever sees its own `GET /fleet/specs`. Each spec is tagged with its\n`tenant` so the executor can namespace container names + resolve secrets\nper-tenant. Declared BEFORE `/fleet/specs/{name}` so `all` isn't read as a name.","operationId":"list_all_fleet_specs_fleet_specs_all_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/specs/{name}":{"get":{"summary":"Get Fleet Spec","operationId":"get_fleet_spec_fleet_specs__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Fleet Spec","operationId":"delete_fleet_spec_fleet_specs__name__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/routers/auth-changes":{"get":{"summary":"Router Auth Changes","operationId":"router_auth_changes_fleet_routers_auth_changes_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Since"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/routers":{"get":{"summary":"List Fleet Routers","operationId":"list_fleet_routers_fleet_routers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/routers/{router_id}/status":{"post":{"summary":"Set Fleet Router Status","operationId":"set_fleet_router_status_fleet_routers__router_id__status_post","parameters":[{"name":"router_id","in":"path","required":true,"schema":{"type":"string","title":"Router Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouterStatusRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/routers/{router_id}/heartbeat":{"post":{"summary":"Fleet Router Heartbeat","operationId":"fleet_router_heartbeat_fleet_routers__router_id__heartbeat_post","parameters":[{"name":"router_id","in":"path","required":true,"schema":{"type":"string","title":"Router Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouterHeartbeatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/routers":{"get":{"summary":"Library Routers","operationId":"library_routers_library_routers_get","parameters":[{"name":"tenant","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/token":{"get":{"summary":"Oci Token","description":"Exchange a fleet credential for a registry bearer token.\n\nDocker sends `Authorization: Basic base64(user:password)` here, where the password is the\ncaller's fleet token. The collector already authenticates Bearer tokens on every other route,\nso the \"minted\" token IS that fleet token echoed back — validated first, never issued blind.\n\nThat keeps identity intact: the follow-up /v2 requests carry a real fleet token, so\n`require_read_or_emit` resolves the actual producer rather than trusting a claimed username.\nNo second token type, no HMAC, no key to rotate.","operationId":"oci_token_v2_token_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v2/":{"get":{"summary":"Oci Root","description":"The v2 handshake. 200 means \"I speak the registry API\"; 401 + WWW-Authenticate starts the\nlogin dance. Auth is checked inline rather than via Depends so the challenge header is present\non the rejection.","operationId":"oci_root_v2__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v2/fleet/{base}/{flavor}/manifests/{ref}":{"get":{"summary":"Get Oci Manifest","description":"GET and HEAD both, and the 401 carries the challenge.\n\nThe containerd image-store resolver (docker 29 with the containerd snapshotter) requests the\nMANIFEST first and does a HEAD before the GET. The legacy resolver hits /v2/ first, picks the\nchallenge up there and caches a token, so it never needed either. Two consequences, both of\nwhich broke pulls on a containerd host while the same registry served a legacy host fine:\n\n  * a 401 from Depends(require_read_or_emit) carries no WWW-Authenticate, so containerd has\n    nothing to act on and gives up rather than fetching a token;\n  * FastAPI does not synthesise HEAD from a GET route, so the HEAD probe got 405.","operationId":"get_oci_manifest_v2_fleet__base___flavor__manifests__ref__get","parameters":[{"name":"base","in":"path","required":true,"schema":{"type":"string","title":"Base"}},{"name":"flavor","in":"path","required":true,"schema":{"type":"string","title":"Flavor"}},{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"head":{"summary":"Get Oci Manifest","description":"GET and HEAD both, and the 401 carries the challenge.\n\nThe containerd image-store resolver (docker 29 with the containerd snapshotter) requests the\nMANIFEST first and does a HEAD before the GET. The legacy resolver hits /v2/ first, picks the\nchallenge up there and caches a token, so it never needed either. Two consequences, both of\nwhich broke pulls on a containerd host while the same registry served a legacy host fine:\n\n  * a 401 from Depends(require_read_or_emit) carries no WWW-Authenticate, so containerd has\n    nothing to act on and gives up rather than fetching a token;\n  * FastAPI does not synthesise HEAD from a GET route, so the HEAD probe got 405.","operationId":"get_oci_manifest_v2_fleet__base___flavor__manifests__ref__head","parameters":[{"name":"base","in":"path","required":true,"schema":{"type":"string","title":"Base"}},{"name":"flavor","in":"path","required":true,"schema":{"type":"string","title":"Flavor"}},{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/fleet/{base}/{flavor}/blobs/{digest}":{"get":{"summary":"Get Oci Blob","description":"Synthesized config blobs are served inline; layer blobs 307 to ghcr.\n\nSame as the manifest route: HEAD is answered, and the 401 carries the challenge.","operationId":"get_oci_blob_v2_fleet__base___flavor__blobs__digest__get","parameters":[{"name":"base","in":"path","required":true,"schema":{"type":"string","title":"Base"}},{"name":"flavor","in":"path","required":true,"schema":{"type":"string","title":"Flavor"}},{"name":"digest","in":"path","required":true,"schema":{"type":"string","title":"Digest"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"head":{"summary":"Get Oci Blob","description":"Synthesized config blobs are served inline; layer blobs 307 to ghcr.\n\nSame as the manifest route: HEAD is answered, and the 401 carries the challenge.","operationId":"get_oci_blob_v2_fleet__base___flavor__blobs__digest__head","parameters":[{"name":"base","in":"path","required":true,"schema":{"type":"string","title":"Base"}},{"name":"flavor","in":"path","required":true,"schema":{"type":"string","title":"Flavor"}},{"name":"digest","in":"path","required":true,"schema":{"type":"string","title":"Digest"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/_strata":{"get":{"summary":"List Strata","operationId":"list_strata_v2__strata_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Put Stratum","description":"Ingest a stratum. The caller supplies digests READ BACK FROM GHCR — never locally computed.\n\n`docker push` compresses with its own settings, so a locally re-compressed layer lands in the\nregistry under a DIFFERENT digest. An index built from local tarballs describes blobs that\nexist nowhere, and the registry then silently serves bytes itself instead of redirecting.","operationId":"put_stratum_v2__strata_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/_strata/impact":{"get":{"summary":"Strata Impact","description":"Answer \"if I change this stratum, what happens?\" so nobody has to recall a design doc.\n\nA flavor rides a new base FOR FREE when its own layers are pure content (source, config,\nstatic binaries). It must be REBUILT when those layers contain something compiled against the\nbase -- a venv, a native extension -- because the interpreter ABI and site-packages path move\nwith it. That is exactly the MINOR/MAJOR distinction, made queryable.\n\n`abi_coupled` is DECLARED at ingest rather than inferred: a `COPY --from` of a venv is\nindistinguishable from any other COPY in the layer history, so guessing would be worse than\nasking.","operationId":"strata_impact_v2__strata_impact_get","parameters":[{"name":"base","in":"query","required":false,"schema":{"type":"string","default":"","title":"Base"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/desired-state":{"post":{"summary":"Add Desired State Candidate","operationId":"add_desired_state_candidate_fleet_desired_state_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesiredStateCandidateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Desired State","operationId":"get_desired_state_fleet_desired_state_get","parameters":[{"name":"channel","in":"query","required":false,"schema":{"type":"string","default":"active","title":"Channel"}},{"name":"version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/desired-state/versions":{"get":{"summary":"List Desired State Versions","operationId":"list_desired_state_versions_fleet_desired_state_versions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/desired-state/promote":{"post":{"summary":"Promote Desired State","operationId":"promote_desired_state_fleet_desired_state_promote_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/desired-state/rollback":{"post":{"summary":"Rollback Desired State","operationId":"rollback_desired_state_fleet_desired_state_rollback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/live/ingest":{"post":{"tags":["fleet-live"],"summary":"Fleet Live Ingest","operationId":"fleet_live_ingest_fleet_live_ingest_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Fleet Live Ingest Fleet Live Ingest Post"}}}}}}},"/fleet/live/snapshot":{"get":{"tags":["fleet-live"],"summary":"Fleet Live Snapshot","operationId":"fleet_live_snapshot_fleet_live_snapshot_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fleet Live Snapshot Fleet Live Snapshot Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/live/sse":{"get":{"tags":["fleet-live"],"summary":"Fleet Live Sse","description":"`event: snapshot` once, then `event: tick` each second there was traffic, `event: state`\n(fleet scope) when router state changes, `: ping` after 15 s of silence. No replay and no\nLast-Event-ID: the tape is ephemeral, a reconnect starts from a fresh snapshot.","operationId":"fleet_live_sse_fleet_live_sse_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/scope":{"get":{"tags":["fleet-live"],"summary":"Fleet Scope","description":"What the Fleet page may offer this caller. The UI hides the scope switch unless\n`fleet` is true — but the UI is never the control; every endpoint re-checks.\n\n`data_url` (docs/fleet-data-plane-design.md §3.2) is the central fleetcache's base URL\nfrom `AGENT_MDX_FLEET_DATA_URL`, or null while it is unset — the UI's switch between the\ndata plane (mint an `aud=fleetcache` token, read the cache) and today's collector path.\n\n`fleet_tenant` (fleet operators only, else null) names the workspace that owns the fleet base\ntable, so the UI's \"Whole fleet\" scope can open its credentials and routing table.","operationId":"fleet_scope_fleet_scope_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Fleet Scope Fleet Scope Get"}}}}}}},"/fleet/agents/{name}/ask":{"post":{"summary":"Ask Agent","operationId":"ask_agent_fleet_agents__name__ask_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Ask Agent Fleet Agents  Name  Ask Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/tickets":{"get":{"summary":"List Tickets","operationId":"list_tickets_fleet_tickets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/tickets/{ticket_id}":{"get":{"summary":"Get Ticket","operationId":"get_ticket_fleet_tickets__ticket_id__get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"string","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/agents/{name}/reports":{"get":{"summary":"Operator Reports","operationId":"operator_reports_fleet_agents__name__reports_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/decisions":{"get":{"summary":"Pending Decisions","operationId":"pending_decisions_fleet_decisions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/agents/{name}/tickets":{"post":{"summary":"File Ticket","operationId":"file_ticket_fleet_agents__name__tickets_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/agents/{name}/agent-intake":{"get":{"summary":"Get Intake","operationId":"get_intake_fleet_agents__name__agent_intake_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Intake","operationId":"put_intake_fleet_agents__name__agent_intake_put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Intake","operationId":"delete_intake_fleet_agents__name__agent_intake_delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/usage":{"get":{"tags":["fleet-usage"],"summary":"Fleet Usage","operationId":"fleet_usage_fleet_usage_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","default":"7d","title":"Window"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fleet Usage Fleet Usage Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/global-admin/tokens":{"post":{"summary":"Mint Global Admin Token","description":"Mint a global-admin token. Only an existing global admin (or break-glass) may\nmint one — tenant admins (incl. the default/home admin) cannot. The first-run\nbootstrap mints the initial global admin; break-glass is the ultimate recovery.\nReturns the plaintext once; only the hash is stored.\n\n#1114 (owner default A): a listed person's elevated browser SESSION may not mint one: a lasting\nglobal-admin token would outlive the 12 h elevation and the session itself. Minting stays behind\na pasted global-admin token or break-glass (`require_global_admin_token`: 403, `details.reason` =\n`pasted_token_required`, audited).","operationId":"mint_global_admin_token_global_admin_tokens_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalAdminTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Global Admin Tokens","description":"Global-admin tokens (metadata + id only — never the plaintext/hash), oldest first. Active\nones by default; `?include_revoked=true` also lists revoked ones (with who/when/why).","operationId":"list_global_admin_tokens_global_admin_tokens_get","parameters":[{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Revoked"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/global-admin/tokens/{token_id}/revoke":{"post":{"summary":"Revoke Global Admin Token","description":"Revoke one global-admin token by id (GLOBAL admin or break-glass only).\n\n* The token itself is refused from the next request on every collector auth path\n  (`_deps._resolve_global_admin`, used by resolve_request_token, require_global_admin,\n  is_global_admin and the fleet scope, reads the in-memory registry on each request — nothing\n  caches the verdict). Open SSE streams close at their next auth re-check (≤\n  AGENT_MDX_SSE_AUTH_RECHECK_S, default 60 s). NOT revoked: OIDC JWTs it already minted via\n  POST /auth/token — consumers verify those offline against the JWKS, so they stay valid until\n  their own `exp` (fleetcache ≤ 600 s, world-sim ≤ 3600 s; oidc._AUD_TTL), nor tokens it\n  minted (`issued_by`). Survives a restart (JSONL replay keeps the last line per hash and\n  revocation is terminal; bootstrap does not re-mint while the registry holds any row).\n* Idempotent: a revoked token is 200 with `already_revoked: true`, no second audit line.\n* Self-revoke (the token this request is authenticated with) needs `?confirm=self`, else 409\n  `confirm_self_revoke` and nothing changes.\n* Never strands the platform: revoking the last ACTIVE global-admin token is refused 409\n  `last_admin` unless the env break-glass (AGENT_MDX_BREAKGLASS_ADMIN) is configured — even\n  with confirm. Recovery then is break-glass → POST /global-admin/tokens.\n* Audited to the global audit log as `global_admin.revoked` with the acting admin\n  (owner id + credential id or `breakglass`).","operationId":"revoke_global_admin_token_global_admin_tokens__token_id__revoke_post","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}},{"name":"confirm","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirm"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tenants":{"get":{"summary":"List Tenants","operationId":"list_tenants_tenants_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Tenant","operationId":"create_tenant_tenants_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tenants/current":{"get":{"summary":"Tenant Current","description":"Public: identify the tenant this Host resolves to (id, display_name, read_only).\nNo auth — the SPA calls it pre-login to enter read-only demo mode on a demo host.","operationId":"tenant_current_tenants_current_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/plans":{"get":{"summary":"Tenant Plans","description":"Public pricing for self-serve tenant sign-up (backs the marketplace CTA).","operationId":"tenant_plans_tenants_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/mine":{"get":{"summary":"My Tenants","description":"The caller's tenants (human session) with plan + trial state — backs the\naccount \"Your tenants\" list. Members-only fields (tokens) are never included.","operationId":"my_tenants_tenants_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/new":{"post":{"summary":"New Unpaid Tenant","description":"Buying a workspace must always be possible, also after the free trial was used (P0): this\ncreates (or returns the caller's existing) workspace on plan=`unpaid` — READ-ONLY until its\nfirst paid subscription (tenant_access `awaiting_payment`; routes/billing._fulfil_subscription\nsets plan=paid). It grants nothing for free and does not consume or start a trial; the buyer\nthen subscribes it through the normal /billing/checkout (target=tenant, plan=subscribe).","operationId":"new_unpaid_tenant_tenants_new_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/trial":{"post":{"summary":"Start Trial","description":"Self-serve: a logged-in human spins up their own tenant on a free trial — no\nglobal-admin needed. Random 8-char id, hostname <id>.<base>, owner membership for\nthe caller. No card → 24h. One trial per person, of either kind: someone who opened a\n3-day card-trial checkout gets no no-card trial (#1154), and their older still-open card-trial\ncheckouts are closed before this one starts. A user may own several tenants (capped to deter\nabuse).","operationId":"start_trial_tenants_trial_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/free-seller":{"post":{"summary":"Start Free Seller","description":"#1277 — free publish & sell: give a signed-in human ONE seller workspace on plan `free_seller`\nwith no subscription and no trial clock (collector/free_selling.py). Idempotent: an existing one\n(also one upgraded to a full plan since) is returned, never a second. 404 while\nAGENT_MDX_FREE_SELLING is off, so the path answers exactly as an unknown route did.","operationId":"start_free_seller_tenants_free_seller_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/publish-targets":{"get":{"summary":"Library Publish Targets","description":"Seller tenants the caller could publish a saved session into (admin/owner of an active,\nnon-personal tenant). Empty when they only have a personal library — the UI then explains that\nselling needs a paid tenant.","operationId":"library_publish_targets_library_publish_targets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/router-token/{tenant}":{"post":{"summary":"Library Router Token","description":"Self-serve emitter token for the a4sx fleet-router, scoped to a PAID tenant the caller owns/admins — which is all it takes, since the router comes with a paid workspace and there is no addon to buy. Mints a FRESH `ge_tok_` bound to the tenant's approved producer; only the hash persists. Use it as the API key with base_url=<router>; usage meters that tenant. The tenant supplies its OWN upstream (see /library/router-config).","operationId":"library_router_token_library_router_token__tenant__post","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/router-config/{tenant}":{"post":{"summary":"Library Router Config","description":"Publish a tenant's OWN provider upstream (BYO) into its vault so the fleet-router can serve it.\nStores the credential + a `router-routes` config in the tenant's vault and grants the router\nproducer read on both. Scoped server-side to the target tenant (the vault is Host-scoped), so the\napex-hosted web + CLI can both call it. The fleet never lends its provider account.\n\nBody: {route?, model, secret_name?, credential, force?}. `route` defaults to \"openrouter\" (which\nreads the fixed `openrouter` secret); other routes name their credential secret via `session`.\nRefuses with 409 `would_clobber_agents` when the stored table carries per-agent policies\n(published via PUT /library/router-routes/{tenant} or by hand) unless `force: true`.","operationId":"library_router_config_library_router_config__tenant__post","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/ensure":{"post":{"summary":"Ensure Personal Library","description":"Self-serve, idempotent: give a logged-in human a FREE personal library. The library lives\non the APEX under their account — everything (/library/push, /library/sessions, resume) is\nreached on the host they're already on; there is no subdomain to switch to. Returns just a\nconfirmation; clients push to the same origin they logged in on.","operationId":"ensure_personal_library_library_ensure_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/profiles":{"get":{"summary":"List Launch Profiles","description":"All of the caller's named launch profiles + which id is the default.","operationId":"list_launch_profiles_library_profiles_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/profile":{"get":{"summary":"Get Launch Profile","description":"One profile — `?name=<id>`, else the default. Empty fields mean 'use the client\ndefault'. Backs the CLI/wrapper. The API key / router token is never stored here.","operationId":"get_launch_profile_library_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/profiles/{pid}":{"put":{"summary":"Put Launch Profile","description":"Create/update a named profile. Body is the profile object (or {profile:{…}}); only\nknown non-secret fields are kept and credential headers are stripped.","operationId":"put_launch_profile_library_profiles__pid__put","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Launch Profile","operationId":"delete_launch_profile_library_profiles__pid__delete","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/profiles/{pid}/default":{"post":{"summary":"Set Default Launch Profile","operationId":"set_default_launch_profile_library_profiles__pid__default_post","parameters":[{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/sessions":{"get":{"summary":"List Library Sessions","description":"The caller's SAVED sessions — the staged (private) collections in their personal library,\neach wrapping a session. Read-only; scoped to the caller's own personal tenant.","operationId":"list_library_sessions_library_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/journey":{"get":{"summary":"Library Journey","description":"Where the caller is on your-saved-sessions → install → profile → resume, each with its next action.\nProgress is computed from real state (signed in, sessions saved to your library, launch\nprofiles). A machine/anon caller gets the static steps (all not-done).","operationId":"library_journey_library_journey_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/tenants/{tenant_id}/admin-tokens":{"post":{"summary":"Mint Tenant Admin Token","description":"GLOBAL admin: mint a tenant-admin token for an existing tenant (e.g. to add an\noperator, or recover a lost tenant-admin token). The minted token is a PURE tenant\nadmin — it lives in that tenant's admin store, scoped to that tenant; it is NOT a\nglobal admin. Returns the plaintext once.","operationId":"mint_tenant_admin_token_tenants__tenant_id__admin_tokens_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantAdminTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Tenant Admin Tokens","description":"The tenant's admin tokens — metadata and id only, never the plaintext or hash.","operationId":"list_tenant_admin_tokens_tenants__tenant_id__admin_tokens_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tenants/{tenant_id}/admin-tokens/{token_id}/revoke":{"post":{"summary":"Revoke Tenant Admin Token","description":"Revoke one tenant-admin token by id. Takes effect on the next request (token lookup reads\nthe in-memory registry, which the upsert updates) and survives a restart (JSONL replay keeps\nthe last line per hash). Idempotent: revoking a revoked token is 200 with `already_revoked`.\n\nRevoking the token the request itself is authenticated with locks the caller out, so it must\nbe explicit: without `?confirm=self` it is refused 409 `confirm_self_revoke` and nothing\nchanges.","operationId":"revoke_tenant_admin_token_tenants__tenant_id__admin_tokens__token_id__revoke_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}},{"name":"confirm","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirm"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tenants/{tenant_id}":{"get":{"summary":"Get Tenant","operationId":"get_tenant_tenants__tenant_id__get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Tenant","operationId":"patch_tenant_tenants__tenant_id__patch","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantPatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Tenant","description":"Soft-delete a tenant. Allowed for a GLOBAL admin OR the tenant's own OWNER (self-serve).\nGitHub-style guard: the caller must echo the id via `?confirm=<tenant_id>`, so a delete can't\nfire by accident. `default` is protected; a personal library is managed automatically, not\ndeleted here.","operationId":"delete_tenant_tenants__tenant_id__delete","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"confirm","in":"query","required":false,"schema":{"type":"string","default":"","title":"Confirm"}},{"name":"owner_unreachable","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Owner Unreachable"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/global-admin/tenant-deletions":{"get":{"summary":"Tenant Deletion Audit","description":"#1311 follow-up (owner item 3): the bounded, READ-ONLY affected-tenant audit — every\nsoft-deleted / purged workspace with its deletion reason (`unknown` when none was stamped), when,\npurged or not, ever billed or not, the billing evidence (subscription ids + local status,\nfulfilled checkouts, €0-coupon subscriptions) and whether it can be restored. Sourced from the\nregistry tombstones, the erasure ledger and the billing store (collector/deletion_audit.py), never\nfrom the event log. `limit` 1–200 (default 50), `cursor` from `next_cursor`; `reason` and\n`ever_billed=true` filter. Ids only: the tenant id and the owner's user id.","operationId":"tenant_deletion_audit_global_admin_tenant_deletions_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Cursor"}},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},{"name":"ever_billed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Ever Billed"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tenants/{tenant_id}/restore":{"post":{"summary":"Restore Tenant","description":"#1311 E: undo a workspace SOFT-delete (global admin only). Refuses when the data dir is\nalready purged — that needs the single-tenant backup restore first (an ops step, not this\nroute). Appends a `tenant_restore` erasure-ledger line (so the boot replay never re-tombstones\nit), sets the plan from live billing, un-hides members' library copies, audits\n`tenant.restored`, emits the `tenant.restored` platform event and mails the owner.","operationId":"restore_tenant_tenants__tenant_id__restore_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/schema":{"post":{"summary":"Register Schema","operationId":"register_schema_model__env__schema_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelSchemaRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Schema","operationId":"get_schema_model__env__schema_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/entities/{type}":{"get":{"summary":"List Entities","operationId":"list_entities_model__env__entities__type__get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"type","in":"path","required":true,"schema":{"type":"string","title":"Type"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/entities/{type}/{key}":{"get":{"summary":"Get Entity","operationId":"get_entity_model__env__entities__type___key__get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"type","in":"path","required":true,"schema":{"type":"string","title":"Type"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes":{"post":{"summary":"Register Process","operationId":"register_process_model__env__processes_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessRegisterRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Processes","operationId":"list_processes_model__env__processes_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes/{pid}/advance":{"post":{"summary":"Advance Process","operationId":"advance_process_model__env__processes__pid__advance_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessAdvanceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes/{pid}":{"delete":{"summary":"Retire Process","description":"Retire a process from the graph. Auto-discovery surfaces candidates by\nfolding the stream, and some are false positives (control-plane chatter, near-\nduplicates) — the model needs a way to drop them so coverage isn't diluted by\nnoise. Idempotent-ish: 404 if it was never registered.\n\n1e — retire is coverage-affecting (it shrinks the denominator), so when 'retire'\nis enforced it must carry an audited `reason`, and an at_target process can only\nbe retired by an admin (you can't silently drop a completed process to reshape\ncoverage).","operationId":"retire_process_model__env__processes__pid__delete","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/coverage":{"get":{"summary":"Get Coverage","operationId":"get_coverage_model__env__coverage_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/recheck":{"post":{"summary":"Recheck Env","description":"Drift sweep (Phase 4): re-evaluate the env's at_target processes against their\nlive governed evidence. Any that no longer hold (faithfulness SLO breach / fitness\nbelow target) are flipped to `drifted`, their loop is reopened, and an operator\ninbox card is filed. Idempotent + debounced (one open card per process). Drive it\non a schedule (a watchdog-style adapter or a cron subscription) for hands-off\nself-healing; call it directly for an on-demand re-check.","operationId":"recheck_env_model__env__recheck_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/discover":{"post":{"summary":"Discover Env","description":"Phase 3 rung 1 — mine the env's OWN events over a window into a friction-\nranked automation backlog (recurring high-friction processes worth automating\nfirst). Read-only; the register side already exists (POST .../processes).","operationId":"discover_env_model__env__discover_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/synthesize":{"post":{"summary":"Synthesize Env","description":"Phase 3 rung 2 — the DETERMINISTIC gap analysis: required (proposer-supplied)\n− provided → an AUTOMATION candidate (nothing missing) or a DEPENDENCY candidate\n(wire the missing capabilities in first). The requirement-derivation is the\nclient-side LLM step; this set-difference is the governance hinge.","operationId":"synthesize_env_model__env__synthesize_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/frontier":{"get":{"summary":"Get Frontier","description":"Frontier-coverage breakdown (frontier-coverage/v0.1): resolved vs open\ndimensions, distinctness, redundant processes. Empty (enabled:false) for envs\nwith no frontier_policy — a legacy env must not receive frontier verdicts it\nnever opted into.","operationId":"get_frontier_model__env__frontier_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/graph":{"get":{"summary":"Get Graph","description":"The process schematic — nodes + derived flow edges + active + dangling-input\n(discovery targets). Backs the UI 'circuit' view (how processes wire into the\nenv's dev lifecycle, what's worked on now, and where inputs come from).","operationId":"get_graph_model__env__graph_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/discovery":{"get":{"summary":"Get Discovery","description":"The discovery question-tree for an environment: per axis (breadth /\nobservation / characterization / automation), what discovery has ANSWERED vs\nwhat is still OPEN. Backs the UI discovery tree-view.","operationId":"get_discovery_model__env__discovery_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/faithfulness-spec":{"post":{"summary":"Register Faithfulness Spec","description":"Register a GOVERNED FaithfulnessSpec (1a): it names the INDEPENDENT ground-\ntruth source + the passing threshold the collector uses to RECOMPUTE the reading.\nAdmin-only, immutable, versioned — the loop authors the schema, never the thing\nthat grades it. The threshold can't be below the governed floor\n(faithfulness_min_threshold), which kills the 'threshold=0.0 clears it' hole.","operationId":"register_faithfulness_spec_model__env__faithfulness_spec_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaithfulnessSpecRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Faithfulness Specs","operationId":"list_faithfulness_specs_model__env__faithfulness_spec_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/faithfulness":{"post":{"summary":"Record Faithfulness","description":"Record/refresh a held-out faithfulness reading. When a GOVERNED FaithfulnessSpec\nexists for (env, scope) the collector RECOMPUTES the reading from the schema\nprojection vs. independent ground truth (1a) and IGNORES any caller-supplied\nscore/threshold. With no spec it falls back to the legacy caller-reported reading\n(backward-compatible). Either way it folds the latest + emits\nmodel.faithfulness.measured.","operationId":"record_faithfulness_model__env__faithfulness_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaithfulnessRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Faithfulness","description":"The latest faithfulness readings for an environment: the env-wide model\n(scope=_model) + per-process. For any scope with a GOVERNED spec the reading is\nRECOMPUTED live (so the trust-meter can't drift from a stale POST); scopes with\nonly a legacy reading are returned as stored. Backs the UI trust-meter.","operationId":"get_faithfulness_model__env__faithfulness_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes/{pid}/request_authorization":{"post":{"summary":"Request Authorization","description":"The loop records that a process's SHADOW champion (a generated automation\nthat met its target) awaits human live-authorization — it lands in the\ninbox. The loop requests; only a human (admin) authorizes.","operationId":"request_authorization_model__env__processes__pid__request_authorization_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/authorizations":{"get":{"summary":"List Authorizations","description":"The human-leaf inbox: shadow champions awaiting (or having received) a\nlive-authorization decision, for this environment.","operationId":"list_authorizations_model__env__authorizations_get","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes/{pid}/authorize":{"post":{"summary":"Authorize Process","description":"The human gate (admin only): authorize the shadow champion for live use.\nThe collector records + emits loop.authorized; the actual deploy stays\nexternal/CI (the collector grants authorization, it does not push code).","operationId":"authorize_process_model__env__processes__pid__authorize_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationDecisionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/model/{env}/processes/{pid}/reject":{"post":{"summary":"Reject Authorization","description":"The human gate (admin only): reject the shadow champion.","operationId":"reject_authorization_model__env__processes__pid__reject_post","parameters":[{"name":"env","in":"path","required":true,"schema":{"type":"string","title":"Env"}},{"name":"pid","in":"path","required":true,"schema":{"type":"string","title":"Pid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationDecisionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/resolve":{"post":{"summary":"Resolve Capability","description":"Resolve a missing capability to the best resolution strategy. The ranking\nencodes the architecture: reuse an existing event > extend an adapter that\nalready integrates the source > build a new adapter > loop_fetch (anti-pattern);\na credential the agent can't mint → escalate to a human (the leaf).","operationId":"resolve_capability_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/artifacts/validate":{"post":{"summary":"Validate Artifact","description":"The deterministic gate on a generated automation artifact: the meta-path\nguard (never a fitness/signing/schema/spec file — a loop can't rewrite how it's\ngraded) + a syntax check. Returns {valid, reasons}. The artifact is DATA here;\nthe collector never executes it.","operationId":"validate_artifact_artifacts_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactValidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/topics/{topic}/sensitivity":{"post":{"summary":"Set Topic Sensitivity","description":"Mark a topic `open` or `restricted` (admin-only). Idempotent\nlast-write-wins. Emits a `topic.sensitivity_set` meta-event.","operationId":"set_topic_sensitivity_topics__topic__sensitivity_post","parameters":[{"name":"topic","in":"path","required":true,"schema":{"type":"string","title":"Topic"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopicSensitivityRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/topics":{"get":{"summary":"List Topics","description":"List every topic with an explicit sensitivity record. Topics not\nlisted here default to `open`.","operationId":"list_topics_topics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/read-tokens":{"get":{"summary":"List Read Tokens","operationId":"list_read_tokens_read_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Read Token","operationId":"create_read_token_read_tokens_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadTokenCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/read-tokens/{rid}/revoke":{"post":{"summary":"Revoke Read Token","operationId":"revoke_read_token_read_tokens__rid__revoke_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens":{"get":{"summary":"List Unified Tokens","operationId":"list_unified_tokens_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Unified Token","description":"Mint a single `ge_tok_`. Plaintext returned ONCE; only the hash persists.","operationId":"create_unified_token_tokens_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedTokenCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/{tid}/revoke":{"post":{"summary":"Revoke Unified Token","operationId":"revoke_unified_token_tokens__tid__revoke_post","parameters":[{"name":"tid","in":"path","required":true,"schema":{"type":"string","title":"Tid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/pr/{owner}/{repo}/{number}":{"get":{"summary":"Get Pr","operationId":"get_pr_entities_pr__owner___repo___number__get","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string","title":"Owner"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string","title":"Repo"}},{"name":"number","in":"path","required":true,"schema":{"type":"integer","title":"Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Pr Entities Pr  Owner   Repo   Number  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/ticket/{system}/{key}":{"get":{"summary":"Get Ticket","operationId":"get_ticket_entities_ticket__system___key__get","parameters":[{"name":"system","in":"path","required":true,"schema":{"type":"string","title":"System"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Ticket Entities Ticket  System   Key  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/epic/{system}/{key}":{"get":{"summary":"Get Epic","operationId":"get_epic_entities_epic__system___key__get","parameters":[{"name":"system","in":"path","required":true,"schema":{"type":"string","title":"System"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Epic Entities Epic  System   Key  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/repo/{owner}/{repo}":{"get":{"summary":"Get Repo","operationId":"get_repo_entities_repo__owner___repo__get","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string","title":"Owner"}},{"name":"repo","in":"path","required":true,"schema":{"type":"string","title":"Repo"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Repo Entities Repo  Owner   Repo  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/polaris":{"get":{"summary":"List Polaris","description":"List polaris baseline pointers. `?stale=true` → only services whose\nbaseline is behind the current develop ref (a re-learn is due).","operationId":"list_polaris_entities_polaris_get","parameters":[{"name":"stale","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stale"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Polaris Entities Polaris Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/account_usage":{"get":{"summary":"List Account Usage","description":"Subscription usage for the Atlas Usage tab: per-(org,window) rolling-\nwindow usage (used/remaining/resets_at, latest from the usage-poller's\naccount.usage events) + the agent↔account allocation matrix (which agent\nused which account_id, folded from account_id on lifecycle events).","operationId":"list_account_usage_entities_account_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Account Usage Entities Account Usage Get"}}}}}}},"/entities/usage_traffic":{"get":{"summary":"Usage Traffic","description":"The caller tenant's router pay-per-use metrics for a calendar month\n(default: the current month). Bytes are RAW in+out traffic through the fleet\nrouter. Rows are scoped to the CALLER's own tenant (resolved from Host, never\ncaller-supplied) against the central ledger. `totals` carries the billable\noverage math (1 GB free, then €0.10/GB).","operationId":"usage_traffic_entities_usage_traffic_get","parameters":[{"name":"month","in":"query","required":false,"schema":{"type":"string","default":"","title":"Month"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Usage Traffic Entities Usage Traffic Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/polaris/{service}":{"get":{"summary":"Get Polaris","description":"The baseline pointer for a service: current source_ref, content_hash,\nURIs (spec + cached develop-cascade), and staleness vs latest develop.","operationId":"get_polaris_entities_polaris__service__get","parameters":[{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Polaris Entities Polaris  Service  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/pr":{"get":{"summary":"List Prs","operationId":"list_prs_entities_pr_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"repository","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"}},{"name":"ticket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ticket"}},{"name":"epic","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Epic"}},{"name":"is_held","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Held"}},{"name":"has_gate_failing","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Gate Failing"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Prs Entities Pr Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/ticket":{"get":{"summary":"List Tickets","operationId":"list_tickets_entities_ticket_get","parameters":[{"name":"system","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System"}},{"name":"key_prefix","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Key Prefix"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Tickets Entities Ticket Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/epic":{"get":{"summary":"List Epics","operationId":"list_epics_entities_epic_get","parameters":[{"name":"system","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System"}},{"name":"key_prefix","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Key Prefix"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Epics Entities Epic Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/repo":{"get":{"summary":"List Repos","operationId":"list_repos_entities_repo_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Repos Entities Repo Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/needs_human":{"get":{"summary":"List Needs Human","description":"List NeedsHumanRequest entities, newest-first by last_event_at.\n\nThe Atlas Inbox view's primary call is `?state=open` — that's the\nsubstrate-wide \"what's blocked on a human?\" inbox.\n\nGlobal-admin-only kinds (collector/needs_human_visibility.py, e.g. the EU B2C revenue threshold)\nare left out for every other caller; a page may then hold fewer than `limit` rows. For a global\nadmin, the body of such a card is filled in from its read-restricted record.","operationId":"list_needs_human_entities_needs_human_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by lifecycle state: open | acknowledged | resolved | dismissed | escalated. Most consumers want `state=open` (the inbox).","title":"State"},"description":"Filter by lifecycle state: open | acknowledged | resolved | dismissed | escalated. Most consumers want `state=open` (the inbox)."},{"name":"producer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Producer"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"repository","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repository"}},{"name":"pr","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pr"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Needs Human Entities Needs Human Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/needs_human/{request_id}":{"get":{"summary":"Get Needs Human","operationId":"get_needs_human_entities_needs_human__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Needs Human Entities Needs Human  Request Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/entities/event_types":{"get":{"summary":"List Event Types","description":"Return every event_type that's ever been emitted, with\ncumulative count + first/last seen timestamps.\n\nBacks the Atlas Workflows view's \"all event-type rows are\nalways visible\" feature. Cheap aggregation (single GROUP BY\nover the events table, index-supported).","operationId":"list_event_types_entities_event_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Event Types Entities Event Types Get"}}}}}}},"/entities/tokens":{"get":{"summary":"List Tokens","description":"One row per token, folding the three token stores + the per-producer\nemit footprint + the topic-sensitivity registry, with DERIVED roles/grants\nand a SHADOW `shadow_would_deny` (computes-but-never-enforces).\n\nAdmin-only — token metadata is sensitive. See specs/authz/v0.1.md\n\"Tokens projection\".","operationId":"list_tokens_entities_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Tokens Entities Tokens Get"}}}}}}},"/champions":{"get":{"summary":"List Champions","operationId":"list_champions_champions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/champions/{target}":{"get":{"summary":"Get Champion","operationId":"get_champion_champions__target__get","parameters":[{"name":"target","in":"path","required":true,"schema":{"type":"string","title":"Target"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fitness":{"get":{"summary":"List Fitness","operationId":"list_fitness_fitness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Fitness","operationId":"register_fitness_fitness_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FitnessRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fitness/{name}":{"get":{"summary":"Get Fitness","operationId":"get_fitness_fitness__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/loops":{"get":{"summary":"List Loops","operationId":"list_loops_loops_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Loop","operationId":"register_loop_loops_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoopRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/loops/{loop_id}/approve":{"post":{"summary":"Approve Loop","operationId":"approve_loop_loops__loop_id__approve_post","parameters":[{"name":"loop_id","in":"path","required":true,"schema":{"type":"string","title":"Loop Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/loops/{loop_id}/kill":{"post":{"summary":"Kill Loop","operationId":"kill_loop_loops__loop_id__kill_post","parameters":[{"name":"loop_id","in":"path","required":true,"schema":{"type":"string","title":"Loop Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/loops/{loop_id}/publish":{"post":{"summary":"Publish Loop","description":"Mediated promotion (specs/improvement-loop/v0.2 §S5). The loop NEVER\nwrites a bundle; the collector (promoter) verifies the gates and SIGNS the\nchampion with the vault/k8s key the loop cannot reach. This records a signed\npublish authorization + emits loop.published; the actual bundle delivery to\nthe skills repo is an external/CI step that carries this signature, which the\nbundle store verifies before serving (verify-before-serve).","operationId":"publish_loop_loops__loop_id__publish_post","parameters":[{"name":"loop_id","in":"path","required":true,"schema":{"type":"string","title":"Loop Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/replay":{"post":{"summary":"Replay","operationId":"replay_replay_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/actions/needs_human/{request_id}/approve":{"post":{"summary":"Needs Human Approve","description":"#1311 follow-up / #1317 n5: approve ONE paid-workspace review card. A HUMAN global admin only\n(`require_human_global_admin`: a listed person's own session; every API token is 403). Declared\nbefore the generic action route, so `approve` never reaches it.","operationId":"needs_human_approve_actions_needs_human__request_id__approve_post","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Needs Human Approve Actions Needs Human  Request Id  Approve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/actions/needs_human/{request_id}/{action}":{"post":{"summary":"Needs Human Action","operationId":"needs_human_action_actions_needs_human__request_id___action__post","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","title":"Action"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Needs Human Action Actions Needs Human  Request Id   Action  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/inbox/items":{"get":{"summary":"Inbox Items","operationId":"inbox_items_inbox_items_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Inbox Items Inbox Items Get"}}}}}}},"/inbox/stream":{"get":{"summary":"Inbox Stream","operationId":"inbox_stream_inbox_stream_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/inbox/answer":{"post":{"summary":"Inbox Answer","description":"Answer one box: `{repo, number, item_id, choice?, text?, request_id}` → the posted answer.\n`choice` must be one of the box's options as the inbox parsed them; `text` is free text (≤ 2000\ncharacters). At least one is needed. A repeated `request_id` returns the first result.","operationId":"inbox_answer_inbox_answer_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Inbox Answer Inbox Answer Post"}}}}}}},"/inbox/answer-origin":{"get":{"summary":"Inbox Answer Origin","description":"Is GitHub comment `comment_id` a genuine inbox answer? `verified` is true only when GitHub\nsays the comment's author is the inbox App's bot AND a `decision.answered` audit line names it\nand still matches it (issue, box id, request id, body hash). The rule for anyone acting on an\nanswer: act only on `verified: true`. `repo` (optional) looks up a comment the audit doesn't\nknow, to report its author. Read-only; owner only; 404 unless both inbox flags are on.","operationId":"inbox_answer_origin_inbox_answer_origin_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Inbox Answer Origin Inbox Answer Origin Get"}}}}}}},"/actions/goal/{event_id}/resolve":{"post":{"summary":"Resolve Stuck Goal","operationId":"resolve_stuck_goal_actions_goal__event_id__resolve_post","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resolve Stuck Goal Actions Goal  Event Id  Resolve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/actions/goal/{event_id}/resume":{"post":{"summary":"Resume Held Goal","operationId":"resume_held_goal_actions_goal__event_id__resume_post","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","title":"Event Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resume Held Goal Actions Goal  Event Id  Resume Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agents/{name}/manifest":{"get":{"summary":"Get Manifest","operationId":"get_manifest_agents__name__manifest_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Manifest","operationId":"patch_manifest_agents__name__manifest_patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agents":{"get":{"summary":"List Agents","operationId":"list_agents_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/specs":{"get":{"summary":"List Specs","operationId":"list_specs_specs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/specs/{name}/versions":{"get":{"summary":"Spec Versions","operationId":"spec_versions_specs__name__versions_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/specs/{name}/latest":{"get":{"summary":"Spec Latest","operationId":"spec_latest_specs__name__latest_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/specs/{name}/v{version}":{"get":{"summary":"Spec Version","operationId":"spec_version_specs__name__v_version__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Spec","description":"Copy-on-write a spec (specs/multi-tenancy/v0.1 Phase 3). Body is the raw\nmarkdown. A GLOBAL admin writes the global runtime overlay (platform-wide);\na tenant admin writes its own tenant's override (shadows the baked library\nfor that tenant only). On-disk presence is the source of truth — no\nversions.json bump needed (it is enumerated).","operationId":"put_spec_specs__name__v_version__put","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skills":{"get":{"summary":"List Skills","operationId":"list_skills_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/skills/{full_path}/versions":{"get":{"summary":"Skill Versions","operationId":"skill_versions_skills__full_path__versions_get","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skills/{full_path}/latest":{"get":{"summary":"Skill Latest","operationId":"skill_latest_skills__full_path__latest_get","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skills/{full_path}/v{version}":{"get":{"summary":"Skill Version","operationId":"skill_version_skills__full_path__v_version__get","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Skill","description":"Copy-on-write a skill (specs/multi-tenancy/v0.1 Phase 3, mirrors\n`put_spec`). Body is the raw markdown. A GLOBAL admin writes the platform-wide\nskill overlay; a tenant admin publishes into its own tenant's skill library\n(shadows the baked tree for that tenant only). On-disk presence is the source\nof truth — no versions.json bump needed (it is enumerated).","operationId":"put_skill_skills__full_path__v_version__put","parameters":[{"name":"full_path","in":"path","required":true,"schema":{"type":"string","title":"Full Path"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/subscriptions":{"post":{"summary":"Create Subscription","operationId":"create_subscription_subscriptions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"get":{"summary":"List Subscriptions","operationId":"list_subscriptions_subscriptions_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/subscriptions/sse":{"get":{"summary":"Stream Sse","operationId":"stream_sse_subscriptions_sse_get","parameters":[{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/subscriptions/{subscription_id}":{"get":{"summary":"Get Subscription","operationId":"get_subscription_subscriptions__subscription_id__get","parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Subscription","operationId":"delete_subscription_subscriptions__subscription_id__delete","parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent-skills/{skill_id}/{version}/sign":{"post":{"summary":"Sign Bundle","description":"Sign a served bundle for verify-before-serve (1g). Admin-only: the collector\nsigns {skill_id, version, content_hash} with the GOVERNED key (never loop-\naccessible) and stores the signature. 503 if no key is configured.","operationId":"sign_bundle_agent_skills__skill_id___version__sign_post","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent-skills":{"get":{"summary":"List Skills","description":"Index: every skill with its served `latest` version + content_hash.\n\nMirrors `GET /polaris-baselines`. Without this there's no enumeration entry\npoint — a caller must already know a skill_id (the per-skill routes 404 on\nunknown ids), and a bare `GET /agent-skills` would fall through to the SPA\ncatch-all and return dashboard HTML.","operationId":"list_skills_agent_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/agent-skills/{skill_id}/versions":{"get":{"summary":"List Versions","description":"List known versions of a skill, newest-first.\n\nRegistered BEFORE the `{version}` catch route so the literal `/versions`\nsegment isn't captured as a version name.","operationId":"list_versions_agent_skills__skill_id__versions_get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent-skills/{skill_id}/{version}":{"get":{"summary":"Get Manifest","description":"Return the manifest record for the (skill_id, version). `latest` resolves\nto a concrete version via the projection's channel ref.","operationId":"get_manifest_agent_skills__skill_id___version__get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/agent-skills/{skill_id}/{version}/{path}":{"get":{"summary":"Get File","description":"Return the body of a file in the bundle.","operationId":"get_file_agent_skills__skill_id___version___path__get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skill-projection":{"get":{"summary":"Index","operationId":"index_skill_projection_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/skill-projection/{skill_id}/versions":{"get":{"summary":"Versions","operationId":"versions_skill_projection__skill_id__versions_get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skill-projection/{skill_id}/channels/{channel}":{"get":{"summary":"Channel","operationId":"channel_skill_projection__skill_id__channels__channel__get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"channel","in":"path","required":true,"schema":{"type":"string","title":"Channel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skill-projection/{skill_id}/{version}":{"get":{"summary":"Manifest","operationId":"manifest_skill_projection__skill_id___version__get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skill-projection/{skill_id}/{version}/{path}":{"get":{"summary":"File Body","operationId":"file_body_skill_projection__skill_id___version___path__get","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/skill-projection/{skill_id}/publish":{"post":{"summary":"Publish","description":"Validated publish (the write engine; spec §5.4 made real). Runs the\nrequired checks ('CI'), auto-bumps the semver version from the projection's\ncurrent latest (GitVersion-style: default patch; `+semver: minor|major` in\n`message` overrides, or an explicit `bump`), and emits a `skill.published`\nevent (which folds into the projection). Body:\n    {files:[{path, content|content_b64}], bump?, message?, set_latest?}\nReturns 201 {version, ...} or 422 {checks:[...]} on a failed check.\n\nSurface note: this is the engine every write path drives; the git `push`\n(gitflow) surface is a later increment that validates + calls this same core.","operationId":"publish_skill_projection__skill_id__publish_post","parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","title":"Skill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/publish/guided":{"post":{"summary":"Publish Guided","operationId":"publish_guided_memory_publish_guided_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/purchase-requests":{"post":{"summary":"Create Purchase Request","description":"Start a purchase for the human to confirm (#780). Body `{id, tenant, version?}`: the listing\n(collection id and its seller workspace, from search results) and optionally the version the\nagent expects (default `latest`; any other must be the version on sale now). Needs a scoped\nlibrary token with `library:acquire`. Returns 201 with `purchase_request_id`, a short\n`user_code` and the `verify_url` the human opens; poll GET /library/purchase-requests/{id}.\nNothing is charged here, and the agent never receives a payment session.","operationId":"create_purchase_request_library_purchase_requests_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/purchase-requests/{rid}":{"get":{"summary":"Get Purchase Request","description":"Poll a purchase request (#780): `pending` (stage `awaiting_confirmation` or\n`awaiting_payment`), `completed` (with `acquired_copy_id`, the private library copy), `declined`\nor `expired`. Only the user and tenant that made it see it; anything else is 404.","operationId":"get_purchase_request_library_purchase_requests__rid__get","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/decision-requests":{"post":{"summary":"Create Decision Request","description":"Ask the key's user to answer one open needs-human request of the bound workspace. Nothing is\nanswered here: the person opens `verify_url`, checks the code and answers there.","operationId":"create_decision_request_fleet_decision_requests_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/decision-requests/{rid}":{"get":{"summary":"Get Decision Request","operationId":"get_decision_request_fleet_decision_requests__rid__get","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/tags":{"get":{"summary":"List Tags","description":"Tag catalog for the tenant — {tag: count}. Backs the filter UI. Registered\nbefore the `{mid}` routes so `tags` isn't captured as a memory id.","operationId":"list_tags_memory_tags_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/leaderboard":{"get":{"summary":"Leaderboard","description":"Top items/collections by distinct-tenant imports + top authors by karma.\nAll figures derive from real events (imports/ratings/promotes). QA / test accounts and their\nlistings are excluded (analytics A0.1); a global admin may pass `include_test=true` for the raw\nfigures (ignored for everyone else).","operationId":"leaderboard_memory_leaderboard_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/bounties":{"get":{"summary":"List Bounties","description":"The request board — open (and filled) memory/session requests. #1149 review: a bounty filled\nwith an item that is not publicly listed right now (e.g. a non-Claude listing while the harness\nflag is off) does not name it: `fills_with` reads null, the bounty stays `filled`.","operationId":"list_bounties_memory_bounties_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Post Bounty","description":"Post a request to the bounty board. Body: {title, detail?, tags?}.","operationId":"post_bounty_memory_bounties_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/discover":{"get":{"summary":"Discover","description":"Cross-tenant PUBLIC browse/search over promoted memories, sessions and\ncollections. Empty `q` = ranked browse. `kind`/`tag` are comma-separated\nfilters; `sort` ∈ {relevance, imports, rating, recent}. Only promoted-`latest`\nitems appear (private collections excluded) — the same public set as the mirror.\n\n`topic=tag:<slug>` / `topic=category:<slug>` (#999) keeps the listings of one topic page\n(collector/topics.py: the slug, so every spelling of a tag counts) and adds `topic` to the\nresponse: {kind, slug, name, count, indexable} — the same facts the server-rendered\n/marketplace/<kind>/<slug> page is built from (collector/topic_pages.py). It does not combine\nwith `access` (400): that lists the viewer's own items, unfiltered.\n\n`access=accessible|acquired` lists the VIEWER's items instead (everything they can load, or\nonly what they didn't author), newest first, filtered before paging so nothing older than a\npage is lost. `q`/`tag`/`sort` don't apply there; an anonymous viewer gets an empty list.\n\n`harness=<id>[,<id>…]` (#867 PR 8, additive) keeps the listings recorded with those harnesses\n(`claude-code`, `codex-cli`, `gemini-cli`, `opencode`, `grok-build`, `unknown`; the aliases `claude`,\n`codex`, `gemini`, `grok` work too). An unregistered value is a 400. With the harness flag on, every row carries\n`labels` and `facets.harness` counts listings per harness (collector/harness_labels.py).","operationId":"discover_memory_discover_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kind"}},{"name":"tag","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tag"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"relevance","title":"Sort"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"access","in":"query","required":false,"schema":{"type":"string","default":"","title":"Access"}},{"name":"topic","in":"query","required":false,"schema":{"type":"string","default":"","title":"Topic"}},{"name":"harness","in":"query","required":false,"schema":{"type":"string","default":"","title":"Harness"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/discover/facets":{"get":{"summary":"Discover Facets","description":"Global tag + kind facets over the public catalog (backs the filter rail).","operationId":"discover_facets_memory_discover_facets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/discover/item":{"get":{"summary":"Discover Item","description":"ONE listing, shaped like a discover row for this viewer (UX-01: the listing page no longer\ndownloads the whole catalogue to find one row). Only PUBLIC collections are answerable — the\ndiscovery index holds nothing else — so a private, staging or taken-down id is a 404 for\neveryone, indistinguishable from an unknown one. `t` = the owning tenant (else resolved).","operationId":"discover_item_memory_discover_item_get","parameters":[{"name":"id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Id"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/discover/preview":{"get":{"summary":"Discover Preview","description":"#779 (owner 2026-10-05, option 1A): the owner-only DRAFT PREVIEW of a collection —\nshaped like `/memory/discover/item` so the listing page can render it — for members of the\ncollection's OWNING workspace only (the people who can read its drafts today, `is_member_of`).\nNo share link. Everyone else (anonymous, a signed-in stranger, a buyer, another tenant's\nmember or machine token, a library token, the analyst) gets the SAME 404 the public\n`discover/item` answers for an unknown id, so the route is no existence oracle.\n\nThe owning tenant is the REQUEST's tenant (its hostname), never a `?t=`/`?tenant=` override:\na member previews their own workspace's drafts on its own host. The row is built on demand and\nnever enters the discovery index, so search, facets, sitemap, the author page and MCP stay\nunaware of it. A preview is not a storefront view: no `collection.viewed`, no KPI counter.","operationId":"discover_preview_memory_discover_preview_get","parameters":[{"name":"id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/authors/{handle}":{"get":{"summary":"Author Profile","description":"A public author page: their profile (if the credit maps to a real account)\nplus every public item credited to that handle. `handle` is the attribution\nstring shown on cards (a user handle, or a free-form credit).","operationId":"author_profile_memory_authors__handle__get","parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string","title":"Handle"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/library-token":{"post":{"summary":"Mint Library Token","description":"Logged-in human: mint a scoped, expiring read token for agents to pull library items.\nReturns the plaintext ONCE.","operationId":"mint_library_token_memory_library_token_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Revoke Library Tokens","description":"Logged-in human: revoke every library token they minted.","operationId":"revoke_library_tokens_memory_library_token_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/entitlements/grant":{"post":{"summary":"Grant Entitlement","description":"Grant an entitlement to consume a paid/private item. Body:\n{kind, id, subject:\"user:<uid>\"|\"tenant:<tid>\", expires_at?}. Emits\n`entitlement.granted`; the commerce webhook (Phase 4) uses the same event.","operationId":"grant_entitlement_memory_entitlements_grant_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/entitlements/revoke":{"post":{"summary":"Revoke Entitlement","description":"Revoke an entitlement — the admin counterpart of `/memory/entitlements/grant` (ACC-039: a\ngrant made through the pre-Stage-A hole had no way back). Global admin only. Body:\n{kind, id, subject, tenant? (item grants), reason}. Emits a plain `entitlement.revoked` — no\ndispute id, so it never tombstones an acquired copy (that is the refund path's job). It does bar a\nchargeback won later, before or after it, from reinstating what it withdrew (#1165).","operationId":"revoke_entitlement_memory_entitlements_revoke_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/pricing":{"post":{"summary":"Set Pricing","description":"Declare an item buyable (or free). Body: {kind, id, amount_cents, currency?=usd}.\namount_cents<=0 clears the price (free). Mutable — no re-promote. Refreshes the\ndiscovery card so the price shows immediately. The credited author or an admin.","operationId":"set_pricing_memory_pricing_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/pricing/history":{"get":{"summary":"Pricing History","description":"The listing's price history, oldest first (#691). Seller (credited author) or admin only —\nD3-A: buyers never see it, and nothing in it is ever rendered as a discount (D2-A).","operationId":"pricing_history_memory_pricing_history_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/pricing/preset":{"get":{"summary":"Get Price Preset","description":"The listing's price preset and, once inside its 7-day notice window, the next step its\nschedule asks for (`next_step`, else null). Seller/admin only; never shown to buyers.","operationId":"get_price_preset_memory_pricing_preset_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Set Price Preset","description":"Choose the listing's price preset (#691 D1-B). Body: {kind, id, preset, params?}.\npreset: keep_current | gentle_decay {floor_cents?} | launch_to_target {target_cents} |\nmajor_reset {base_cents} (collections only) | custom_schedule {start_cents, target_cents,\ncadence_days, drop_pct} (#691 stage 2: the seller's own schedule, opt-in). For the platform\npresets today's price becomes the starting price; custom_schedule starts at its own start_cents.\nChoosing again re-anchors the schedule and resumes a paused rule. Floors and bounds are validated here.\nStage 1: steps are only reported (dry run), never executed — see collector/price_rules.py.","operationId":"set_price_preset_memory_pricing_preset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/provenance":{"post":{"summary":"Set Provenance","description":"The credited author (or an admin) states where an item came from. Body:\n{kind, id, provenance: {origin, agent?, model?, source?, derived_from?, validated_by?,\nvalidation?, notes?}} — an empty provenance clears it. Shown on the card; audited as\n`marketplace.provenance.set`.","operationId":"set_provenance_memory_provenance_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/studio":{"get":{"summary":"Seller Studio","description":"The seller's cockpit: everything credited to the logged-in human — drafts in this\ntenant's staging area and published items across tenants — with the real signals a\nbuyer sees (imports, ratings, verified, sales), the price, provenance, a topic-specific\nreputation, and the bounties they posted. Machine tokens: 401.","operationId":"seller_studio_memory_studio_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/journey":{"get":{"summary":"Buyer Journey","description":"Where the caller is on discover → trust → acquire → bundle → run → outcomes → publish,\nwith the exact next UI action and API call. Progress is computed from real state (library,\nbundles, minted library tokens, ratings/reports, credited items); machine tokens get the\nstatic steps.","operationId":"buyer_journey_memory_journey_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/attribution":{"post":{"summary":"Set Attribution","description":"Credit an item to its author. Body: {kind, id, author}. Empty author clears the\noverride (falls back to the content's declared author, then the promoter). Mutable —\nno re-promote. Refreshes the discovery card so the credit shows immediately.","operationId":"set_attribution_memory_attribution_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory":{"get":{"summary":"List Memories","description":"Memories by channel — published (`stage=latest`, default) or the staging\narea (`?stage=staging`), optionally filtered to a single `?tag=`. Each row\ncarries its (mutable) tags. Powers the UI's memory-management view.","operationId":"list_memories_memory_get","parameters":[{"name":"stage","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Stage"}},{"name":"tag","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tag"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections":{"get":{"summary":"List Collections","description":"Published collections by default (`stage=latest`). Authors/curators can\nlist the staging area with `?stage=staging`.","operationId":"list_collections_memory_collections_get","parameters":[{"name":"stage","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Stage"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}":{"get":{"summary":"Get Collection","operationId":"get_collection_memory_collections__cid__get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Version"}},{"name":"tenant","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/bundle":{"get":{"summary":"Collection Bundle","description":"Everything a consumer needs to import a collection in ONE call: the manifest\nplus every member memory resolved to a concrete version with its file bytes\n(base64). This is what the `memory import` CLI fetches — one request instead of\nN. Defaults to the published (`latest`) collection; `?version=staging` gives an\nauthor a preview of the draft. `?tenant=` names the owning tenant for a collection\npublished by another tenant (auto-resolved from discovery when omitted). Registered\nBEFORE the `{version}` route so the literal `/bundle` segment isn't captured as a version.","operationId":"collection_bundle_memory_collections__cid__bundle_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Version"}},{"name":"tenant","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/releases":{"get":{"summary":"Collection Releases","description":"Published-version history — each release with level, changelog, member diff, deprecated flag.\nRegistered BEFORE the `{version}` route so `releases` isn't captured as a version name.\nAnonymous-readable for a PUBLIC collection only (UX-02); a non-member of the owning tenant gets\n404 for staging/private and never sees the sign-off name (`by`). `?t=` names the item tenant.","operationId":"collection_releases_memory_collections__cid__releases_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/diff":{"get":{"summary":"Collection Diff","description":"What changed in a version — the release record for `to` (defaults to latest): changelog +\nmember diff. Registered BEFORE the `{version}` route so `diff` isn't captured as a version.","operationId":"collection_diff_memory_collections__cid__diff_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","default":"","title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/upgrade":{"get":{"summary":"Collection Upgrade","description":"For the CALLER: the version they're pinned to vs latest, and whether a newer MAJOR\n(a paid upgrade) is available. `upgrade` ∈ current | free | paid | not_entitled.\nRegistered before the `{version}` catch-all so `upgrade` isn't read as a version.","operationId":"collection_upgrade_memory_collections__cid__upgrade_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/{version}":{"get":{"summary":"Get Collection Version","operationId":"get_collection_version_memory_collections__cid___version__get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions":{"get":{"summary":"List Sessions","description":"Sessions by channel — the rendered-narrative artifact kind. Same shape as\n`GET /memory`, keyed to the `session` kind.","operationId":"list_sessions_memory_sessions_get","parameters":[{"name":"stage","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Stage"}},{"name":"tag","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tag"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/versions":{"get":{"summary":"Session Versions","operationId":"session_versions_memory_sessions__sid__versions_get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/{version}":{"get":{"summary":"Session Manifest","operationId":"session_manifest_memory_sessions__sid___version__get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/{version}/{path}":{"get":{"summary":"Session File","operationId":"session_file_memory_sessions__sid___version___path__get","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/versions":{"get":{"summary":"Memory Versions","operationId":"memory_versions_memory__mid__versions_get","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/{version}":{"get":{"summary":"Memory Manifest","operationId":"memory_manifest_memory__mid___version__get","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/{version}/{path}":{"get":{"summary":"Memory File","operationId":"memory_file_memory__mid___version___path__get","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}},{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/search":{"get":{"summary":"Search","description":"Phase-1 text/tag search over collection manifests + memory frontmatter — the\nbacking for the on-demand SOP lookup. Phase 2 swaps in the semvec embedder.","operationId":"search_memory_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","default":"","title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/publish":{"post":{"summary":"Publish Memory","operationId":"publish_memory_memory_publish_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/sessions/publish":{"post":{"summary":"Publish Session","description":"Publish a rendered-session bundle (client renders/scrubs/anonymizes the raw\ntranscript first — the raw transcript never reaches the server).","operationId":"publish_session_memory_sessions_publish_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/push":{"post":{"summary":"Library Push","description":"One-call session save (for the agent-paste flow): POST the RAW transcript as the request\nBODY (raw bytes — not JSON, not multipart), with `?label=`/`?title=` query params. The server\nSCRUBS it and stages a PRIVATE collection wrapping it in the caller's personal library. The\nlibrary is resolved from the ACCOUNT (the session token), NOT the request Host — so this works\non the apex you logged in on; there is no subdomain to switch to. Authorization is implicit: a\nsigned-in human can only ever write to their OWN library. An agent can do the whole upload with\none HTTP request after a device-login — no local CLI, no multipart. Never promoted → stays private.\n\nAUTH: a `ge_sess_` session bearer from the device-login. PERSIST that token so resuming later\nneeds no second login — `a4sx login --token <tok>` (writes ~/.config/a4sx/session, chmod 600), or\nexport A4SX_SESSION=<tok>. Clients look it up in this order: $A4SX_SESSION, $AGENT_MDX_SESSION,\n~/.config/a4sx/session, then ~/.config/agent-mdx/session (where older sign-ins saved it). The same\ntoken drives push, fetch, and resume.\n\nRETRIES: send `Idempotency-Key: <uuid>` (one per logical push, the SAME on every retry of it) and\noptionally `X-Content-SHA256: <hex sha256 of the body>`. A repeat of a key already answered within\n24 h with the same bytes returns the ORIGINAL response (200) and stores nothing; the same key with\ndifferent bytes is `409 idempotency_key_reused`. Pushes to one entry are serialized, so a retry that\nlands while the first is still being stored waits for it instead of racing it\n(collector/push_idempotency.py).\n\nWARNINGS: the response may carry an advisory `warnings: [{code, message}]` list; it never changes\nthe status or what is stored. `cli_outdated_pem` (#820): the body contains the client-side\n`[REDACTED-PRIVATE-KEY]` marker and the client is an amdx/a4sx CLI <= 0.10.8 (or sends no a4sx\nUser-Agent), which may have merged transcript lines around that key (#816) — update and push again.\n\nASYNC (large uploads): send `Prefer: respond-async` and the server streams the body to disk, answers\n`202 {job, status_url, ...}` at once and processes the push in the background; poll\n`GET /library/push/jobs/{job}` until `status` is `done` (`result.http_status` + `result.body` = this\nroute's synchronous answer) or `failed` (`error`). Same scrub, same ledger, same answers\n(collector/push_jobs.py). A retry with the same Idempotency-Key attaches to the running job.","operationId":"library_push_library_push_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/library/push/jobs/{job_id}":{"get":{"summary":"Library Push Job","description":"The state of one of the caller's own asynchronous pushes (`POST /library/push` with\n`Prefer: respond-async`): `status` queued | running | done | failed, `stage`, `progress`\n{done, total} (bytes), and once `done` the push's own answer as `result` {http_status, body};\nonce `failed`, `error` {status, code, message, retryable}. Another library's job is 404.","operationId":"library_push_job_library_push_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/craft-demand":{"get":{"summary":"Library Craft Demand","description":"Content-free demand signal for richer part-selection tooling. Aggregates `library.craft` events\n(emitted when `a4sx craft` composes N parts) — no content, no ids, just how often crafts happen, how\nmany parts they compose, and the context-size spread. Size is reported descriptively, never judged\n(no hardcoded 'oversized' threshold), per the size-agnostic stance. `multi_source_crafts` (>=2 parts)\nis the number that matters: build Phase-1 selection tooling once it's consistently non-trivial.\nCrafts by QA / test accounts (the event's actor) are excluded unless `include_test=true` (A0.1).","operationId":"library_craft_demand_library_craft_demand_get","parameters":[{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/acquire/{cid}":{"post":{"summary":"Library Acquire","description":"Import a marketplace item you're ENTITLED to into your PRIVATE library as a launchable base\ncopy, tagged with where it came from (`acquired_from`). This is the bridge: a bought/imported\nsession lives in the SELLER'S tenant and isn't launchable via the library; acquiring stages a\nprivate copy in YOUR personal tenant so `a4sx launch --a4sx-session` and the lineage tree\nwork on it normally.\n\nAccepts a marketplace COLLECTION (its session member is copied) or a bare SESSION listing\n(synthesised as a one-member collection below, so the copy, scrub and provenance are identical).\nReuses the same cross-tenant read + entitlement gate as GET /memory/collections/{cid}/bundle: the\nentitlement check is MANDATORY (a paid item without entitlement → 402). Idempotent: re-acquiring\nthe same source stages a NEW VERSION of the same `col-lib-*` entry.\n\nA collection with NO session member is reading material, not a base → 409 `memory_only` with\nthe two routes that DO serve it (never a silent no-op: the Library lists only what lands here).\n\nThe copy carries a private `acquired_from` provenance field only — NOT a royalty edge. Publishing a\nderivative for cross-author credit is the separate, author-gated marketplace `builds_on` declaration.\nAUTH: your `ge_sess_` session bearer (a human account — the copy lands in your personal library).","operationId":"library_acquire_library_acquire__cid__post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"latest","title":"Version"}},{"name":"tenant","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/fetch":{"get":{"summary":"Library Fetch","description":"Read one of the caller's OWN saved sessions for resume — account-scoped, on the apex (no\nsubdomain). Resolves the collection within the caller's personal library by `cid` (exact) or\n`name` (exact id, then `label:` tag, then title substring), and returns the staged bundle\n(manifest + member files, base64) — the same shape as the marketplace bundle, so the wrapper\ncan pull the transcript. Private, staged; never leaves the caller's library.\n\nAUTH: the caller's own `ge_sess_` session bearer — the SAME token used for the upload. No second\nlogin is needed to resume: persist that token once (`a4sx login --token <tok>`, which writes\n~/.config/a4sx/session chmod 600, or export A4SX_SESSION=<tok>) and every resume reuses it. Lookup\norder: $A4SX_SESSION, $AGENT_MDX_SESSION, ~/.config/a4sx/session, ~/.config/agent-mdx/session (older\nsign-ins). Token handling is a CLIENT concern — the server only checks the bearer; it never stores it.","operationId":"library_fetch_library_fetch_get","parameters":[{"name":"name","in":"query","required":false,"schema":{"type":"string","default":"","title":"Name"}},{"name":"cid","in":"query","required":false,"schema":{"type":"string","default":"","title":"Cid"}},{"name":"version","in":"query","required":false,"schema":{"type":"string","default":"","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session":{"get":{"summary":"Library Session Detail","description":"Detail view of ONE saved session (account-scoped, apex). Metadata + version history + the\nsession's SESSION.md and transcript (base64) + row/byte counts, for the My Sessions detail\npage. Private; never leaves the caller's library.","operationId":"library_session_detail_library_session_get","parameters":[{"name":"cid","in":"query","required":false,"schema":{"type":"string","default":"","title":"Cid"}},{"name":"name","in":"query","required":false,"schema":{"type":"string","default":"","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}":{"get":{"summary":"Library Session Detail Path","description":"Path-style alias of `GET /library/session?cid=` — the bare `GET /library/session/<cid>`\nused to 404 (only the query form resolved), while the `/version/<v>` sub-path worked, an\ninconsistency callers tripped on. Same handler, same account-scoping.","operationId":"library_session_detail_path_library_session__cid__get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Library Session","description":"PERMANENTLY delete a saved session from the caller's PRIVATE library. Fast — no log rewrite in\nthe request: the entry is hidden at once (stops listing; fetch/resume answer 404) and one\nerasure-ledger line (ids and dates only) per item — the private collection and its session\nmember — is appended. That line is the durable commitment: the batched erase worker\n(collector/erasure.deferred_erase_loop) erases every stored version through the GDPR hard-erase\npath within LIBRARY_ERASE_WINDOW_HOURS, many deletes in one log rewrite, and replay_ledger\nre-applies it after any restore. No grace period, no undo. Answers 202 `erasure_scheduled`.\n\nAccount-scoped — a signed-in human can only delete their OWN entries (anything else is 404 and\nnothing is scheduled). Accepts a collection id, a session id, or a name/label (?name=).\nKept, and listed in `retained`: published copies in a workspace, buyers' copies and escrow,\nbilling/entitlement records, forks of this entry, backups until they expire. Idempotent: a\nrepeat answers 202 `erasure_scheduled` until the worker is done, then 200 `already_erased`;\nan unknown id is 404 as before.","operationId":"delete_library_session_library_session__cid__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}/version/{ver}":{"get":{"summary":"Library Session Version","description":"One version's content + what changed since its parent — the \"open the commit\" view. Returns the\nfull transcript at `ver` (for a full read) plus, when this version simply APPENDED to its parent\n(the common backup case), the appended text so the UI can render only the new turns. A wholesale\nrewrite (e.g. a squash) is flagged `rewritten` with coarse ±line counts instead. Account-scoped.","operationId":"library_session_version_library_session__cid__version__ver__get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"ver","in":"path","required":true,"schema":{"type":"string","title":"Ver"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}/meta":{"post":{"summary":"Library Session Meta","description":"Edit a saved session's METADATA (title/label/tags/description) — account-scoped. Re-stages\nthe private collection manifest as a new version; the transcript is untouched. Not a content\neditor (see /scrub for cleaning).","operationId":"library_session_meta_library_session__cid__meta_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}/listing-draft":{"get":{"summary":"Library Session Listing Draft","description":"#1270: a DETERMINISTIC listing draft (title, summary, tags, category) for one of the caller's\nown saved sessions, built only from fixed vocabularies and counts (collector/listing_draft.py), plus\nthe seller-only signals it came from. No model call. Read-only: nothing is saved or published —\nthe seller edits it, saves it with `POST /library/session/{cid}/meta` and publishes through the\nusual flow and its sign-off. Account-scoped (the caller's own library, like every /library/session\nroute). Behind `AGENT_MDX_LISTING_DRAFTS` (default off): off, it answers like an unknown route.","operationId":"library_session_listing_draft_library_session__cid__listing_draft_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}/scrub":{"post":{"summary":"Library Session Scrub","description":"Re-run the secret scrubber over a saved session's transcript — account-scoped.\n`?dry_run=1` returns {findings, would_change} without writing. Otherwise, if the scrub changes\nanything, publishes a new CLEANED session version and bumps the collection manifest to point at\nit (the previous version stays in history).","operationId":"library_session_scrub_library_session__cid__scrub_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"dry_run","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Dry Run"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/session/{cid}/publish-to/{tenant}":{"post":{"summary":"Library Publish To","description":"Bridge a private saved session into a SELLER tenant so it can be listed on the public\nmarketplace. Copies the session item + collection manifest from the caller's personal library\ninto `tenant` (which the caller must own/admin, active, non-personal), as a PUBLIC-visibility\nSTAGED draft. It is NOT promoted here — the user prices + signs off + promotes via the existing\nSell cockpit. Keeps the personal-library copy untouched.","operationId":"library_publish_to_library_session__cid__publish_to__tenant__post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/publish":{"post":{"summary":"Publish Collection","description":"Publish a collection manifest. Body:\n{id, title, description?, members:[{id, version, kind?}], tags?, visibility?,\n price?, license?, version?|bump?, message?, set_latest?}","operationId":"publish_collection_memory_collections_publish_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/collections/{cid}/members":{"post":{"summary":"Edit Collection Members","description":"Incrementally assemble a draft collection: add/remove member memories and/or\nupdate storefront metadata. Each call republishes a new STAGED manifest version\n(immutable audit); the collection stays non-consumable until /promote. Members\nmay reference staged OR published memories while drafting — /promote is what\nenforces that they are all published. Body:\n    {add?:[{id, version, kind?}], remove?:[id, ...], title?, description?, tags?,\n     visibility?, price?, license?}","operationId":"edit_collection_members_memory_collections__cid__members_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/metadata":{"post":{"summary":"Edit Collection Metadata","description":"#999: a METADATA-ONLY edit — change a collection's `tags` and/or `description` and nothing\nelse. `/memory/collections/publish` (and `/members`) rebuild the manifest from a fixed field set,\nwhich drops keys they do not know (an auto-wrapped listing's `wrapped_from`) and adds ones the\nlisting never had (`price`/`author`/`license`). This route reads the stored `collection.json`\nand rewrites only those two values; every other key, the key order and the JSON layout stay as\nstored.\n\nThe result is a new PATCH version, staged exactly like a publish (`staging` channel, immutable).\nIt goes live only through `POST /memory/collections/{cid}/promote` with `signoff_by`, which keeps\nthe member-review gate (members_not_published), the storefront scrub and the dedup gate, and\nrecords the release (level `patch`: free for existing buyers). Auth: the publish route's.\nBody: {tags?: [str], description?: str, base_version?: str}. The base is always the live\nversion (or, when nothing is live, the staged draft: any member changes in it ride along);\n`base_version`, if sent, must name it (409 base_not_current). A newer staged draft on top of the\nlive version is refused (409 newer_draft_staged), never jumped past or displaced; a staged draft\nOLDER than the live version is refused too (409 older_draft_staged; discard it first). A key the\nstored manifest lacks is added.","operationId":"edit_collection_metadata_memory_collections__cid__metadata_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/grant":{"post":{"summary":"Grant Collection","description":"Entitle a tenant/account to a collection (Phase 2 enforcement; Phase 1\nrecords the event). Body: {grantee, note?}. Emits `collection.granted`.","operationId":"grant_collection_memory_collections__cid__grant_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/import":{"post":{"summary":"Import Session","operationId":"import_session_memory_sessions__sid__import_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/import":{"post":{"summary":"Import Collection","operationId":"import_collection_memory_collections__cid__import_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/rate":{"post":{"summary":"Rate Session","operationId":"rate_session_memory_sessions__sid__rate_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/import":{"post":{"summary":"Import Memory","operationId":"import_memory_memory__mid__import_post","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/rate":{"post":{"summary":"Rate Memory","operationId":"rate_memory_memory__mid__rate_post","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/bounties/{bid}/fill":{"post":{"summary":"Fill Bounty","description":"Mark a bounty filled by an item. Body: {fills_with (item id), kind?}.","operationId":"fill_bounty_memory_bounties__bid__fill_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/tags":{"post":{"summary":"Tag Memory","description":"Set a memory's mutable tags. Body: {add?:[...], remove?:[...], set?:[...]}.\nTags are lowercase `[a-z0-9._-]` tokens; invalid ones are dropped. Independent\nof versions/channels — a tag is on the memory id. Returns the new tag set.","operationId":"tag_memory_memory__mid__tags_post","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/{mid}/promote":{"post":{"summary":"Promote Memory","operationId":"promote_memory_memory__mid__promote_post","parameters":[{"name":"mid","in":"path","required":true,"schema":{"type":"string","title":"Mid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/tags":{"post":{"summary":"Tag Session","description":"Set a session's mutable tags (shared tag catalog with memories).","operationId":"tag_session_memory_sessions__sid__tags_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/sessions/{sid}/promote":{"post":{"summary":"Promote Session","description":"Two-key promote for a staged session (auto-scrub + human sign-off). The\nserver re-scrubs the rendered narrative even though the client pre-scrubbed —\ndefense in depth for the largest leak surface (a full transcript).","operationId":"promote_session_memory_sessions__sid__promote_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/promote":{"post":{"summary":"Promote Collection","description":"Promote a staged collection — see `_promote_collection`. On a free seller workspace (#1277)\nthe whole promote runs under that workspace's lock (listing cap + first-N review).","operationId":"promote_collection_memory_collections__cid__promote_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/unpublish":{"post":{"summary":"Unpublish Collection","description":"Admin takedown: clear a collection's `latest` channel so it leaves the marketplace,\nhistory intact and re-promotable (the same reversible mechanism a dispute/analysis takedown\nuses). Body: {reason?}. Use for a security quarantine or a self-serve delist.","operationId":"unpublish_collection_memory_collections__cid__unpublish_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/discard":{"post":{"summary":"Discard Collection Draft","description":"Discard a STAGED, never-listed collection draft: clear its `staging` channel so it leaves the\nSell cockpit. Refuses a live listing (use /unpublish for that). Only the collection's own ref is\ncleared — member sessions/memories are untouched (they may back other, live listings), and the\nversion history stays in the odb, so this is reversible by re-staging. Body: {reason?}.","operationId":"discard_collection_draft_memory_collections__cid__discard_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/collections/{cid}/versions/{version}/deprecate":{"post":{"summary":"Deprecate Collection Version","description":"Withdraw a published version from NEW sales; existing buyers' pins keep resolving.\nWhile the deprecated version is the listed `latest`, the listing is left out of browse,\nsearch and facets (`DiscoveryIndex.is_deprecated`), its row says `sellable:false,\nunsellable_reason:\"version_deprecated\"`, and checkout refuses it (400 `version_deprecated`).\nPromoting a successor lifts all of that. Entitlements and the bundle ignore deprecation.","operationId":"deprecate_collection_version_memory_collections__cid__versions__version__deprecate_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"version","in":"path","required":true,"schema":{"type":"string","title":"Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/scrub-preview":{"post":{"summary":"Scrub Preview","description":"Dry-run the sanitizer WITHOUT publishing or storing anything. Body:\n    {text}                        — scan arbitrary text, or\n    {kind, id, version?=staging}  — scan a STORED item's markdown (collection walks members).\nReturns {findings:[{type,count}], clean, preview (redacted, capped), files?}.\n\nAUTH IS PER-MODE, deliberately. The `{text}` mode is the pre-upload check a brand-new user\nneeds BEFORE they have anything to publish: it reads no stored data, writes nothing, and\nreturns only what the sanitizer found. Gating it behind publish rights — as it was until\n2026-09-22 — meant the one built-in tool for inspecting a transcript before sending it was\nunreachable by exactly the people about to send their first one (measured: 403 for a\nsigned-in user with no tenant, 401 anonymous). Sign-in is still required, because scrubbing\nis CPU-heavy and an anonymous caller could burn the box for free.\n\nThe `{kind, id}` mode still requires publish rights: it READS stored items out of a tenant,\nwhich is a different question from \"scan this text I already have\".\n\nThis endpoint is a BACKSTOP, not the control. Responsibility for what leaves a machine sits\nwith the client: the sanitizer only knows secret SHAPES (sk_/ghp_/whsec_ and friends) and\ncannot know that a hostname, a customer name, or an unreleased product is sensitive to you.\nUse it to catch what you missed, never as the reason you did not look.","operationId":"scrub_preview_memory_scrub_preview_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/providers":{"get":{"summary":"Providers","description":"Which sign-in providers this host offers. `configured: false` is an explicit answer\n(\"no provider is set up here\"); a failure to READ the configuration is a 503, never a\n200 with an empty list — the landing must be able to tell \"no sign-in\" from \"can't reach\nthe server\". Reachable during the startup warm-up (pure env read, see app.py).","operationId":"providers_auth_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/login/{provider}":{"get":{"summary":"Login","operationId":"login_auth_login__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/callback/{provider}":{"get":{"summary":"Callback","operationId":"callback_auth_callback__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/cli/approve":{"post":{"summary":"Cli Approve","description":"The human confirms the code shown matches their terminal — marks the login approved so the\npoller can collect (mint) the session.","operationId":"cli_approve_auth_cli_approve_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/cli/start":{"post":{"summary":"Cli Start","description":"Begin a CLI device-login. Body: {provider?}. Returns a one-time {code} and the {login_url}\nto open in a browser. With NO provider (the default), login_url points at a provider CHOOSER so\nthe user signs in with whatever method their account uses (Google/GitHub/…) — the CLI must not\nguess. A specific `provider` skips the chooser. The CLI then polls /auth/cli/poll?code=.","operationId":"cli_start_auth_cli_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/cli/choose":{"get":{"summary":"Cli Choose","description":"Provider chooser for a pending CLI device-login — the user picks Google/GitHub/… so the CLI\nnever has to guess which method their account uses.","operationId":"cli_choose_auth_cli_choose_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/cli/d/{user_code}":{"get":{"summary":"Cli Short","description":"The short sign-in link printed for a headless host (and encoded in its QR code): resolves the\npairing by the code shown in the terminal and shows the provider chooser. Follows restarts.","operationId":"cli_short_auth_cli_d__user_code__get","parameters":[{"name":"user_code","in":"path","required":true,"schema":{"type":"string","title":"User Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/cli/device":{"get":{"summary":"Cli Device","description":"Type-the-code page (RFC 8628 verification_uri): for signing in from ANOTHER device when the\nterminal's host has no browser. `?c=<code>` jumps straight to the short link.","operationId":"cli_device_auth_cli_device_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/cli/login/{provider}":{"get":{"summary":"Cli Login","description":"Redirect into OAuth for a pending CLI pairing code; the callback binds the\nresulting session to the code (return_to = `cli:<code>`).","operationId":"cli_login_auth_cli_login__provider__get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/cli/poll":{"get":{"summary":"Cli Poll","description":"Poll for a completed CLI login. Returns {session} exactly once (then forgets it),\nelse {status:\"pending\"}; 404 if the code is unknown/expired.","operationId":"cli_poll_auth_cli_poll_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/logout":{"post":{"summary":"Logout","operationId":"logout_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/me":{"get":{"summary":"Me","operationId":"me_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/me/preferences":{"put":{"summary":"Put Preferences","description":"Set the signed-in human's own account preferences. Body `{summary_opt_in: bool}` and/or\n`{sales_report: \"off\" | \"daily\" | \"weekly\" | \"monthly\", sales_report_scope: \"own\" | \"workspace\"}`\n(the seller sales report, #594) and/or `{signup_source: str | null}` — the optional \"How did you\nhear about us?\" answer (collector/signup_source.py, #775): at most 200 characters, scrubbed\nbefore it is stored; \"\" skips the question, null removes an earlier answer. While\nAGENT_MDX_SIGNUP_SOURCE is off every value is refused with 403 `signup_source_off` (nothing is\nrecorded) — except null for an account that still holds an answer, which removes it.\n\nSession-only, like GET /auth/me: a `ge_sess_` bearer from a sign-in. Machine tokens (admin /\nemit / read / unified) and library tokens are refused with 401 `not_logged_in` — consent to\nsending your session text to an LLM is a human's decision, never a token's. There is no user\nid in the path or body, so a caller can only ever change their OWN account.","operationId":"put_preferences_auth_me_preferences_put","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/sales-report/off":{"get":{"summary":"Sales Report Off Page","operationId":"sales_report_off_page_auth_sales_report_off_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Sales Report Off","operationId":"sales_report_off_auth_sales_report_off_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/email-verification":{"get":{"summary":"Get Status","operationId":"get_status_auth_email_verification_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/email-verification/start":{"post":{"summary":"Start","operationId":"start_auth_email_verification_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/email-verification/verify":{"post":{"summary":"Verify","operationId":"verify_auth_email_verification_verify_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/me/identities":{"get":{"summary":"My Identities","description":"The caller's sign-in methods, the providers they can still link (configured on this host and not\nyet on the account — Microsoft only appears once it is configured), whether a link may start now\n(`recent`) or needs a fresh sign-in first, and whether THIS host is where changes happen\n(`manage_here`; else `manage_url`).","operationId":"my_identities_auth_me_identities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/link/{provider}":{"post":{"summary":"Start Link","description":"Start linking `provider` to the signed-in account. Needs a sign-in within the last 10 minutes, on\nthe callback host (409 `wrong_host` elsewhere, with the URL to go to). Returns `{url}` — the SPA\nnavigates the browser there (a top-level navigation, so the provider redirect is not a form action),\nand the cookie set here proves it is the same browser, at the hand-off and again at the callback.","operationId":"start_link_auth_link__provider__post","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/me/identities/{provider}/{ref}":{"delete":{"summary":"Unlink","description":"Remove one sign-in method from the caller's account. Needs a sign-in within the last 10 minutes, on\nthe callback host; the last remaining method can't be removed (409 `last_identity`). Every OTHER\nsession of the account is signed out (the one making the change stays), so a browser that got in with\nthe removed method does not keep access. Agent keys are NOT revoked (#1025 item 2): `active_keys` lists\nthe ones that still work (id, label, dates — never a token), each revocable on its own.","operationId":"unlink_auth_me_identities__provider___ref__delete","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","title":"Provider"}},{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/.well-known/jwks.json":{"get":{"summary":"Jwks","operationId":"jwks__well_known_jwks_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/openid-configuration":{"get":{"summary":"Openid Configuration","operationId":"openid_configuration__well_known_openid_configuration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/auth/token":{"post":{"summary":"Mint Token","description":"Exchange the caller's a4sx credential (human session or machine token, presented as Bearer) for a short-lived JWT the World-Sim (and other consumers) can verify against this issuer's JWKS.","operationId":"mint_token_auth_token_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/gym-tokens/{jti}/revoke":{"post":{"summary":"Revoke Gym Token","description":"Revoke one World-Sim Gym token by its jti (idempotent): the person it was minted for, or a global\nadmin. The jti is then listed at GET /modules/world-sim/revoked until the token expires. 404 while\nAGENT_MDX_GYM_SAMPLE is off, and for a jti that is not a gym token of the caller's.","operationId":"revoke_gym_token_auth_gym_tokens__jti__revoke_post","parameters":[{"name":"jti","in":"path","required":true,"schema":{"type":"string","title":"Jti"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/oidc/keys":{"get":{"summary":"Oidc Key Status","description":"Key-set state (kids and times, never key material) + fleetcache mint counters.","operationId":"oidc_key_status_admin_oidc_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Oidc Key Status Admin Oidc Keys Get"}}}}}}},"/admin/oidc/rotate":{"post":{"summary":"Oidc Rotate","description":"`{step: \"stage\"}` publishes a new key; `{step: \"promote\"}` (≥ 15 min later) makes it the\nsigning key and retires the old one for 2 h. Global admin only.","operationId":"oidc_rotate_admin_oidc_rotate_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Oidc Rotate Admin Oidc Rotate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules":{"get":{"summary":"Modules Catalog","description":"Public catalog of purchasable MODULES (subscriptions). This is the agent-discoverable\nsurface for modules — they are sold separately from content collections and so do NOT appear\nin /memory/discover. Each entry carries the exact call to acquire it.","operationId":"modules_catalog_modules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/modules/world-sim/templates":{"get":{"summary":"World Sim Templates","operationId":"world_sim_templates_modules_world_sim_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/modules/mine":{"get":{"summary":"Modules Mine","operationId":"modules_mine_modules_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/modules/admin/test-expiry/plan":{"get":{"summary":"Test Expiry Plan","description":"S-23 (docs/world-sim-test-expiry-runbook.md): every World-Sim request still `requested`, with\nits age, test/real/uncertain classification, workload evidence and the decision the test-request\nexpiry would take — computed NOW, read-only, whatever AGENT_MDX_MODULE_TEST_EXPIRY says. Plus the\nplan the last `dry_run` / `on` tick recorded. Ids, status, age and classification only.","operationId":"test_expiry_plan_modules_admin_test_expiry_plan_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/modules/world-sim/checkout/{ref}":{"get":{"summary":"World Sim Checkout Arrival","description":"#1130: the World-Sim behind the caller's own checkout `ref` — the post-purchase page polls this\nuntil `stage` is `ready`, then focuses that instance. Owner-only: the caller must resolve to a\nuser (`acting_user_id` — a signed-in human, or a machine token bound to that user; a library\ntoken is refused), and only that user's own checkout and instances are ever read. Anyone else's\nref is a 404, like the checkout status.","operationId":"world_sim_checkout_arrival_modules_world_sim_checkout__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/cancel":{"post":{"summary":"Cancel Module Instance","description":"Cancel ONE World-Sim at the end of its paid period (§ 312k: no further charge, usable until\nthen). Owner-only (a signed-in human, never a library or machine token acting for one); goes\nthrough the same Stripe call, receipt mail and event as `POST /billing/subscriptions/cancel`.\nIdempotent: a second call answers `already_scheduled`. Refuses (409) when the instance's\nsubscription can't be resolved exactly, pointing at /cancel.","operationId":"cancel_module_instance_modules_instances__instance_id__cancel_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/resume":{"post":{"summary":"Resume Module Instance","description":"Keep ONE World-Sim running: withdraw its scheduled end-of-period cancellation (Stripe\n`cancel_at_period_end=false`), so it renews as before. Owner-only human session; the same exact\ninstance → subscription join as cancel (409 → /cancel otherwise). Idempotent (`not_scheduled`\nwhen nothing is scheduled). Refused (409 `period_ended`) once the paid period is over or the\ninstance has ended — that would be a new purchase.","operationId":"resume_module_instance_modules_instances__instance_id__resume_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/snapshot/delete":{"post":{"summary":"Delete Instance Snapshot","description":"Ask the operator to delete an ENDED World-Sim's kept snapshot now instead of after\nSNAPSHOT_RETENTION_DAYS. Owner-only human session; only when `gone` (409 `not_ended`). Emits\n`module.snapshot_delete.requested` once (idempotent: `already_requested` / `already_deleted`).\nCannot be undone. The instance shows `snapshot: delete_requested` until the operator answers\n`module.snapshot_deleted`.","operationId":"delete_instance_snapshot_modules_instances__instance_id__snapshot_delete_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/hide":{"post":{"summary":"Hide Module Instance","description":"Remove an ENDED World-Sim from the owner's list (GET /modules/mine leaves it out unless\n`?include_hidden=1`). Display only: never touches data, the snapshot or billing. Owner-only human\nsession; only when `gone` (409 `not_ended`); idempotent (`already_hidden`).","operationId":"hide_module_instance_modules_instances__instance_id__hide_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/agent-tokens":{"get":{"summary":"List Agent Tokens","description":"The owner's unexpired agent tokens for one World-Sim — metadata only, never a value.","operationId":"list_agent_tokens_modules_instances__instance_id__agent_tokens_get","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Agent Token","description":"Mint an agent token for THIS World-Sim: `{label?, ttl_s?}` (300 s … 1 h). The value is in\nthis response only; afterwards only its metadata can be listed.","operationId":"create_agent_token_modules_instances__instance_id__agent_tokens_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/instances/{instance_id}/agent-tokens/{jti}/revoke":{"post":{"summary":"Revoke Agent Token","description":"Revoke one of the owner's agent tokens for this World-Sim (idempotent).","operationId":"revoke_agent_token_modules_instances__instance_id__agent_tokens__jti__revoke_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}},{"name":"jti","in":"path","required":true,"schema":{"type":"string","title":"Jti"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/world-sim/revoked":{"get":{"summary":"World Sim Revoked","description":"Revoked, not-yet-expired World-Sim agent-token ids of THIS host's tenant (public: a jti of a\nrevoked token grants nothing). For the engine to consult — see the operator contract § 7.","operationId":"world_sim_revoked_modules_world_sim_revoked_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/modules/instances/{instance_id}/board-session":{"post":{"summary":"Board Session","description":"Start a board sign-in for a signed-in owner. Only when the instance's operator advertises\n`endpoints.board_login` (the engine-side half, contract § 7): a single-use 60 s code in the URL\nFRAGMENT (never sent in a request line, so never in a server log), which the board's gateway\nexchanges server-side at POST /modules/world-sim/board/exchange and turns into its own cookie.","operationId":"board_session_modules_instances__instance_id__board_session_post","parameters":[{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","title":"Instance Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/modules/world-sim/board/exchange":{"post":{"summary":"Board Exchange","description":"Server-to-server, called by the board's gateway: `{code}` → a board JWT (`aud: world-sim`,\n`ws_instance`, `ws_use: board`, 10 min). The code is the credential: single-use, 60 s, bound to\none instance; the instance must still be the code issuer's and running. Unavailable (404) while\nper-instance tokens are off; rate-limited per client address.","operationId":"board_exchange_modules_world_sim_board_exchange_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/flywheel/policy":{"get":{"summary":"Get Policy","operationId":"get_policy_flywheel_policy_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Policy Flywheel Policy Get"}}}}}}},"/flywheel/understudy":{"post":{"summary":"Set Understudy","description":"Tenant admin: shadow-run `model` for `agent` (or clear with model=null).","operationId":"set_understudy_flywheel_understudy_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Set Understudy Flywheel Understudy Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/promote":{"post":{"summary":"Promote","description":"Tenant admin: serve the configured understudy for `agent` for real (or demote).","operationId":"promote_flywheel_promote_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Promote Flywheel Promote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/stats":{"get":{"summary":"Stats","description":"The router's stats, with each understudy row stamped with the server's promotion verdict\n(`eligible`, `ineligible_reason`) and the criteria (`promotion_gate`) — the panel shows this\nverdict and holds no thresholds of its own (S-44).","operationId":"stats_flywheel_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/flywheel/models":{"get":{"summary":"Models","operationId":"models_flywheel_models_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/flywheel/export/{what}":{"get":{"summary":"Export","description":"The tenant's own Data-Flywheel data. Default: the tenant's COPY (portability — also open in the\ncancellation grace, WP-20), unchanged and marked `X-A4SX-Training-Gate: not-applied`.\n`?purpose=training`: the harness P1 training gate is applied (collector/harness_policy.py,\n`filter_corpus_tgz`) — this is the only export a training run may consume (runbook step 2). The\nknowledge export has no classifiable records, so it refuses `purpose=training` (fail closed).","operationId":"export_flywheel_export__what__get","parameters":[{"name":"what","in":"path","required":true,"schema":{"type":"string","title":"What"}},{"name":"purpose","in":"query","required":false,"schema":{"type":"string","default":"","title":"Purpose"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/purge":{"delete":{"summary":"Purge","operationId":"purge_flywheel_purge_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/flywheel/training":{"get":{"summary":"Training Status","description":"Is training open, and has this tenant registered interest?","operationId":"training_status_flywheel_training_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Training Status Flywheel Training Get"}}}}}}},"/flywheel/train/interest":{"post":{"summary":"Register Interest","description":"While training is gated: a tenant admin tells us they'd use it. Emits\n`flywheel.train.interest {tenant, agents?, note, by}`; ops read it at GET /flywheel/interest.","operationId":"register_interest_flywheel_train_interest_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Register Interest Flywheel Train Interest Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/interest":{"get":{"summary":"List Interest","operationId":"list_interest_flywheel_interest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Interest Flywheel Interest Get"}}}}}}},"/flywheel/runs":{"get":{"summary":"List Runs","operationId":"list_runs_flywheel_runs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Runs Flywheel Runs Get"}}}}}}},"/flywheel/train":{"post":{"summary":"Request Training","description":"Tenant admin: queue a LoRA training run on this tenant's corpus for `agent` (€49 per\ncompleted run, billed when the adapter is trained). One active run per operator. The run\ncarries a review packet so the launching operator needs nothing else.","operationId":"request_training_flywheel_train_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Request Training Flywheel Train Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/queue":{"get":{"summary":"Training Queue","description":"Every queued/running run across tenants — the launching operator's worklist.","operationId":"training_queue_flywheel_queue_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Training Queue Flywheel Queue Get"}}}}}}},"/flywheel/automation":{"get":{"summary":"Automation Report","description":"S-35: what the manual flywheel chain owes right now (stale queued/running runs, trained\nadapters not served, promotions due review). Read-only — never acts (collector/flywheel_automation.py).","operationId":"automation_report_flywheel_automation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Automation Report Flywheel Automation Get"}}}}}}},"/flywheel/runs/{run_id}/status":{"post":{"summary":"Set Run Status","description":"Operator: started | trained {adapter, adapter_repo?, hours?, notes?, cost_cents?} | failed\n{reason, cost_cents?}. `cost_cents` = what the run cost the platform (S-18, Platform ▸ Modules).","operationId":"set_run_status_flywheel_runs__run_id__status_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Run Status Flywheel Runs  Run Id  Status Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/runs/{run_id}/served":{"post":{"summary":"Mark Served","description":"Operator: the adapter is loaded and routable under router model key `model` — the tenant's\npanel may now offer it as an understudy / promotion target.\n\nfleet-router #62: the fleet table's `models.<model>` is written with `owner` = the adapter's\ntraining-data tenant (collector/flywheel_adapter_owner.py) BEFORE the run is marked served.\n`entry` (optional) is the router target to add; without it the entry must already be in the fleet\ntable. No derivable single owner → 409, nothing written, the run stays trained. Any `owner` /\n`tenant` the caller sends is never used.","operationId":"mark_served_flywheel_runs__run_id__served_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark Served Flywheel Runs  Run Id  Served Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/flywheel/runs/{run_id}/unserved":{"post":{"summary":"Mark Unserved","description":"Operator: take a served adapter out of service — THE intentional unserve path (fleet-router\n#62). Removes the run's router key from the fleet table and marks every run served on it\n`unserved`, atomically. Body: {if_version: int (the fleet table version you read — required),\nreason?: str}. Idempotent: a run that is not served answers 200 with its state, nothing written.","operationId":"mark_unserved_flywheel_runs__run_id__unserved_post","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Mark Unserved Flywheel Runs  Run Id  Unserved Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/fleet/flywheel/entitled":{"get":{"summary":"Flywheel Entitled","operationId":"flywheel_entitled_fleet_flywheel_entitled_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/fleet/tenants/modules":{"get":{"summary":"Fleet Tenants Modules","operationId":"fleet_tenants_modules_fleet_tenants_modules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/qa/user":{"post":{"summary":"Qa User","description":"Mint a fresh synthetic QA human + a login session. The harness hands the returned\n`session` (a `ge_sess_` bearer) to a browser via the `#session=<token>` URL fragment —\nthe same mechanism the OAuth callback uses — so scenarios skip real OAuth.","operationId":"qa_user_qa_user_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/qa/tenant":{"post":{"summary":"Qa Tenant","description":"Provision a fully-seeded, QA-tagged tenant owned by an existing QA user, for publish /\nbuyer scenarios. Reuses the real provisioning path so the tenant behaves like a live one.","operationId":"qa_tenant_qa_tenant_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/qa/fulfil":{"post":{"summary":"Qa Fulfil","description":"Fulfil a pending checkout WITHOUT Stripe, by faithfully replaying the webhook path\n(`billing.webhook`): a one-time buy → `_fulfil` + `mark_fulfilled`; a subscription →\n`link_subscription` + `_fulfil_subscription`. The subscribe branch deliberately mirrors\nthe current code (which never calls `mark_fulfilled`), so S2 reproduces the stuck-`pending`\nbug rather than papering over it.","operationId":"qa_fulfil_qa_fulfil_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/qa/scrub":{"post":{"summary":"Qa Scrub","description":"Soft-delete every QA tenant, RETRACT its published marketplace listings, and revoke its QA\nmemberships. QA users remain (append-only store) but stay namespaced + excluded via\n`is_qa_subject`. Each QA tenant's promoted listings are cleared (reversible takedown) BEFORE the\ntenant is deleted, so no orphans are created.\n\nThe orphan sweep (retract listings whose owning tenant is gone) is OPT-IN only — body\n`{sweep_orphans: true}` — because it is deletion-by-absence: a corrupt/partial `tenants.jsonl`\nreplay could drop a real tenant from the live set and silently retract its storefront. It also\ntakes `{dry_run: true}` (list what it WOULD clear, change nothing) and refuses to clear more than\n`SWEEP_CAP` listings unless `{force: true}`. `default` is always protected.","operationId":"qa_scrub_qa_scrub_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/test-accounts/backfill":{"post":{"summary":"Backfill Test Accounts","description":"Mark existing QA/test accounts with the durable `is_test` flag (analytics A0.1).\n\nDry run by default: returns COUNTS ONLY (no ids, emails or handles) plus the rule text. To\nwrite, send `{\"apply\": true, \"confirm\": \"mark-test-accounts\"}`. Idempotent — already-flagged\naccounts are skipped, so a re-run flags 0. The rule is `synthetic_accounts.BACKFILL_RULE`.","operationId":"backfill_test_accounts_admin_test_accounts_backfill_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/memory/disputes":{"post":{"summary":"Open Dispute","description":"Buyer: report a problem with an item you have access to. Body:\n{kind, id, tenant?=this host, reason: refund|inaccurate|copied|unsafe|other, detail}.\nTakedown reports (copied/unsafe) don't require access.","operationId":"open_dispute_memory_disputes_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"get":{"summary":"List Disputes","description":"What the caller may see: admins everything (optionally `?status=open|answered|resolved`),\na human their own reports plus disputes on items they sell.","operationId":"list_disputes_memory_disputes_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/disputes/{did}/reply":{"post":{"summary":"Reply","operationId":"reply_memory_disputes__did__reply_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/disputes/{did}/resolve":{"post":{"summary":"Resolve","description":"Global admin only (the register is app-global and `refunded` issues a real Stripe refund):\n{outcome: refunded|corrected|taken_down|dismissed, note?, version?}.","operationId":"resolve_memory_disputes__did__resolve_post","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests":{"post":{"summary":"Open Request","description":"Open a support request. Body: {topic, message, context?}. Sign-in required.","operationId":"open_request_support_requests_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"get":{"summary":"List Requests","description":"The Support desk (a global admin, or a person holding `support-reviewer` /\n`support.legal_resolver`) sees every request incl. public reports (optionally `?status=open`,\n`?kind=report`), as full rows. Anyone else signed in sees their OWN requests, projected to the\n`user_row` allowlist.","operationId":"list_requests_support_requests_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"","title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/report":{"post":{"summary":"File Report","description":"PUBLIC notice-and-action intake (no session). Body:\n    {contact (email), item: {kind, id, tenant?}, reason: unsafe|copied|illegal|personal_data|other,\n     detail (20+ chars), name?, good_faith?: true, location?}\n`location` is the notifier's own words for where the content is (the URL or kind:id exactly as\nthey gave it — DSA Art. 16(2)(b) \"exact electronic location\"), kept verbatim next to the\nresolved `item`; the /contact form sends it when it routes a listing notice here.\nRecords the notice, alerts the admins (inbox card) and, if the listing exists, opens a\ndispute so it can be taken down through the normal resolution flow. Rate-limited per IP.","operationId":"file_report_support_report_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/report/{rid}":{"get":{"summary":"Report Status","description":"Public status of a filed report (by its unguessable id).","operationId":"report_status_support_report__rid__get","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/reply":{"post":{"summary":"Reply Request","operationId":"reply_request_support_requests__rid__reply_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/report/{rid}/reply":{"post":{"summary":"Reply Report","operationId":"reply_report_support_report__rid__reply_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/queue":{"get":{"summary":"Operator Queue","description":"The operator's worklist: triaged, non-legal requests (minimal fields). Reviewers / admins get the\nsame view (legal items stay out of it; they read those through GET /support/requests).","operationId":"operator_queue_support_queue_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"open","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/queue/{rid}":{"get":{"summary":"Operator Item","operationId":"operator_item_support_queue__rid__get","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/drafts":{"post":{"summary":"Propose Draft","description":"The operator proposes a reply. Nothing is sent: it waits for a reviewer (SUPPORT_AUTOSEND=off).\nA draft the gate could never pass (legal, unverified sender, a content-filter hit) is refused now.","operationId":"propose_draft_support_requests__rid__drafts_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/drafts/{did}/send":{"post":{"summary":"Autosend Draft","description":"The P2 auto-send attempt. With SUPPORT_AUTOSEND off (the default) the gate refuses EVERY call\n(`autosend_off`); with it on, only allow-listed categories pass. The draft stays pending for a\nreviewer when refused.","operationId":"autosend_draft_support_requests__rid__drafts__did__send_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/escalate":{"post":{"summary":"Escalate","description":"Hand an item up a tier: `coordinator` (tier 2) or `owner` (tier 3; also raises an inbox card).","operationId":"escalate_support_requests__rid__escalate_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/drafts":{"get":{"summary":"List Drafts","operationId":"list_drafts_support_drafts_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"pending","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/drafts/{did}/approve":{"post":{"summary":"Approve Draft","description":"A reviewer approves a draft, optionally with an edited `text` (edit-then-approve sends the\nedited text). The gate still runs (legal, sender, caps, content filter) — on the text that is sent.\nGoes out once through the outbox with the AI-disclosure footer.","operationId":"approve_draft_support_requests__rid__drafts__did__approve_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/drafts/{did}/reject":{"post":{"summary":"Reject Draft","operationId":"reject_draft_support_requests__rid__drafts__did__reject_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"did","in":"path","required":true,"schema":{"type":"string","title":"Did"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/resolve":{"post":{"summary":"Resolve Request","description":"Close an item with an outcome. A legal item needs a global admin or a person holding\n`support.legal_resolver`; a `support-reviewer` (person or token) resolves the rest.","operationId":"resolve_request_support_requests__rid__resolve_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/index/{ref}":{"get":{"summary":"Resolve Index Ref","description":"S-08: the request id behind a GitHub index ref (`ix-<hmac>`, the desk deep link\n`/platform/support#ix-…`). Support-desk roles only — the mapping is never computable client-side.","operationId":"resolve_index_ref_support_index__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/ai-opt-outs":{"get":{"summary":"List Ai Opt Outs","operationId":"list_ai_opt_outs_support_ai_opt_outs_get","parameters":[{"name":"include_removed","in":"query","required":false,"schema":{"type":"string","default":"","title":"Include Removed"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Set Ai Opt Out","description":"Stop the AI support responder for one person. Body: {request_id | user_id | address, reason}.\nFrom an item (`request_id`, the desk action) the person is the row's account (user id) AND its\nrequester address (the sender of an e-mail item — flagged even when unverified: hiding more only\nmeans a human reads it — or the account / notifier address). Idempotent: the same person already\ncovered returns the existing opt-out (200).","operationId":"set_ai_opt_out_support_ai_opt_outs_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/ai-opt-outs/{oid}/remove":{"post":{"summary":"Remove Ai Opt Out","description":"Lift one opt-out (the person withdrew the objection, or it was set in error). Audited.","operationId":"remove_ai_opt_out_support_ai_opt_outs__oid__remove_post","parameters":[{"name":"oid","in":"path","required":true,"schema":{"type":"string","title":"Oid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/actions":{"post":{"summary":"Propose Action","description":"The operator PROPOSES an action. Body {action, workspace?}. Nothing changes here.","operationId":"propose_action_support_requests__rid__actions_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/actions/{aid}/approve":{"post":{"summary":"Approve Action","operationId":"approve_action_support_requests__rid__actions__aid__approve_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"aid","in":"path","required":true,"schema":{"type":"string","title":"Aid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/actions/{aid}/reject":{"post":{"summary":"Reject Action","description":"Reject a proposal, or withdraw an approved link nobody confirmed yet.","operationId":"reject_action_support_requests__rid__actions__aid__reject_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"aid","in":"path","required":true,"schema":{"type":"string","title":"Aid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/actions/{aid}/link":{"get":{"summary":"Action Link","description":"The desk's copy of an approved confirmation link (never stored: recomputed from its signed ids).","operationId":"action_link_support_requests__rid__actions__aid__link_get","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"aid","in":"path","required":true,"schema":{"type":"string","title":"Aid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/requests/{rid}/actions/{aid}/revert":{"post":{"summary":"Revert Action","description":"Undo an executed trial extension: the trial end goes back to what it was. Works with the flag off.","operationId":"revert_action_support_requests__rid__actions__aid__revert_post","parameters":[{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}},{"name":"aid","in":"path","required":true,"schema":{"type":"string","title":"Aid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/action-confirm":{"post":{"summary":"Confirm Action","description":"The confirmation link, for the SIGNED-IN person. Body {t, preview?, workspace?}.\n\nThe token travels ONLY in this POST body: the link carries it in the URL fragment (never sent to a\nserver, so never in an access / error log, a Referer or history sync), the page reads it and posts it.\nA query string on this route is refused before anything else (`token_in_query`), and there is no GET.\n`preview: true` is read-only (what would change; records nothing). Otherwise the action runs for the\nsigned-in person; `workspace` only when the link names none (a trial workspace the person owns).","operationId":"confirm_action_support_action_confirm_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/metrics":{"get":{"summary":"Support Metrics","description":"Aggregates for the desk's Metrics panel. A responder token is 403 (require_support_desk).","operationId":"support_metrics_support_metrics_get","parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"string","default":"7d","title":"Window"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/audit/{week}":{"get":{"summary":"Audit List","operationId":"audit_list_support_audit__week__get","parameters":[{"name":"week","in":"path","required":true,"schema":{"type":"string","title":"Week"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/audit/{week}/{rid}":{"post":{"summary":"Audit Review","operationId":"audit_review_support_audit__week___rid__post","parameters":[{"name":"week","in":"path","required":true,"schema":{"type":"string","title":"Week"}},{"name":"rid","in":"path","required":true,"schema":{"type":"string","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/support/dsar/lookup":{"post":{"summary":"Dsar Lookup","operationId":"dsar_lookup_support_dsar_lookup_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/dsar/export":{"post":{"summary":"Dsar Export","operationId":"dsar_export_support_dsar_export_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/dsar/erase":{"post":{"summary":"Dsar Erase","operationId":"dsar_erase_support_dsar_erase_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/support/dsar/history":{"get":{"summary":"Dsar History","operationId":"dsar_history_support_dsar_history_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/mail/transport-check":{"post":{"summary":"Transport Check","operationId":"transport_check_admin_mail_transport_check_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/mail/template-samples":{"post":{"summary":"Template Samples","description":"One made-up example of every template to {to}, through the normal outbox. ≤ 2 sets an hour.","operationId":"template_samples_admin_mail_template_samples_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/mail/transport-check/{message_id}":{"get":{"summary":"Transport Check Status","operationId":"transport_check_status_admin_mail_transport_check__message_id__get","parameters":[{"name":"message_id","in":"path","required":true,"schema":{"type":"string","title":"Message Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/mail/terms-notice":{"post":{"summary":"Terms Notice Send","operationId":"terms_notice_send_admin_mail_terms_notice_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/syndication/run":{"post":{"summary":"Run","operationId":"run_admin_syndication_run_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/syndication/edit":{"post":{"summary":"Edit","description":"#1256: ONE explicitly requested edit, dry unless the body says {\"dry_run\": false} (and the live switch is on).","operationId":"edit_admin_syndication_edit_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/syndication/status":{"get":{"summary":"Status","operationId":"status_admin_syndication_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/syndication/kit/{slug}":{"get":{"summary":"Kit","operationId":"kit_admin_syndication_kit__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/syndication/reset":{"post":{"summary":"Reset","operationId":"reset_admin_syndication_reset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/blog/posts":{"get":{"summary":"List Posts","operationId":"list_posts_admin_blog_posts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Post","description":"A NEW post as a draft (flag AGENT_MDX_BLOG_AGENT_WRITE): `{slug, fields}`. The slug is free (not in the\nstore yet) and immutable from now on. It goes live only through review + publish.","operationId":"create_post_admin_blog_posts_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/blog/posts/{slug}":{"get":{"summary":"Get Post","operationId":"get_post_admin_blog_posts__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/revisions/{sha}":{"get":{"summary":"Get Revision","operationId":"get_revision_admin_blog_posts__slug__revisions__sha__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"sha","in":"path","required":true,"schema":{"type":"string","title":"Sha"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/diff":{"get":{"summary":"Diff","operationId":"diff_admin_blog_posts__slug__diff_get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","default":"published","title":"From"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","default":"head","title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/images/{name}":{"get":{"summary":"Get Image","operationId":"get_image_admin_blog_images__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/draft":{"put":{"summary":"Put Draft","description":"A new revision of an EXISTING post (PR-1; new posts come with PR-3). `base_sha` must be the head\n(409 `stale_base`); structural problems — an image file name that is not `<slug>[.devto].<sha10>.jpg`\namong them (#1528 review) — are 422 `invalid_post`; content problems are recorded on the revision.","operationId":"put_draft_admin_blog_posts__slug__draft_put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/review-request":{"post":{"summary":"Review Request","operationId":"review_request_admin_blog_posts__slug__review_request_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/reviews":{"post":{"summary":"Review","description":"The review verdict on the head revision (in review): a reviewer's browser session, or (#1303 PR-3, the\nowner's decision on #1303 Q1, flag AGENT_MDX_BLOG_AGENT_PUBLISH) a `blog:publish` token. Bound to that one\nsha: any new revision voids it.","operationId":"review_admin_blog_posts__slug__reviews_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/advisory":{"post":{"summary":"Advisory","description":"An ADVISORY note on a revision (an agent's check, a token holder's verdict). Shown on the review\npage; it never satisfies the review gate and never raises the inbox card.","operationId":"advisory_admin_blog_posts__slug__advisory_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/publish":{"post":{"summary":"Publish","description":"Publish `sha` (the approved head, or — rollback — a revision that was published before). Pinned to the\nsha; every rule re-checked now (collector/blog_publish.py); audited before it happens; idempotent per\n`request_id`. No syndication happens here.","operationId":"publish_admin_blog_posts__slug__publish_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/unpublish":{"post":{"summary":"Unpublish","description":"Take the live post down (410 on its URL, gone from the index, sitemap, RSS and landing). `sha` must be\nthe live revision. Syndicated copies are not touched.","operationId":"unpublish_admin_blog_posts__slug__unpublish_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/images/{name}":{"put":{"summary":"Put Image","description":"Upload ONE rendered image of a post (flag AGENT_MDX_BLOG_AGENT_WRITE). Body: the JPEG bytes\n(`Content-Type: image/jpeg`). Write-once and content-addressed: `name` is `<slug>.<sha10>.jpg` (og,\n1200×630) or `<slug>.devto.<sha10>.jpg` (devto, 1000×420), `<sha10>` the sha256 of exactly these bytes;\nno metadata segments; at most 1 MB. Stored under <data>/blog/post-images/ (safe_image_path + O_NOFOLLOW\nverify). It is used once a draft's `syndication.image.files` names it.","operationId":"put_image_admin_blog_posts__slug__images__name__put","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/posts/{slug}/syndication/go":{"post":{"summary":"Syndication Go","description":"Give the go for some channels of the LIVE revision `sha` (flag AGENT_MDX_BLOG_SYNDICATION_GO):\n`{sha, channels: [...], request_id}`. Records one `blog.post.syndication_go` per channel; the deploy-triggered\nsyndication run then posts that channel ONCE, exactly as for an imported post. A channel the ledger shows as\nposted, or that already has a go for this sha, is a no-op (`already_posted` / `already_go`): nothing is ever\nre-posted. Bound to the live sha: a go for an older revision is refused (409 `stale_sha`).","operationId":"syndication_go_admin_blog_posts__slug__syndication_go_post","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/agent-tokens":{"get":{"summary":"List Agent Tokens","operationId":"list_agent_tokens_admin_blog_agent_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mint Agent Token","description":"Mint a blog agent token (the owner authorizes an agent): `{scopes: [\"blog:write\", \"blog:publish\"],\nlabel, ttl_days?, user_id?}`. Only a PASTED global-admin token or break-glass (an elevated browser session\nis refused: it must not create lasting power, #1114). The token acts as a global-admin PERSON — the one\nthe minting token is bound to, or `user_id` from AGENT_MDX_GLOBAL_ADMIN_USERS — and stops working the\nmoment that person leaves the list, the token is revoked, it expires, or its scope's flag goes off.\nShown once; the registry keeps its hash.","operationId":"mint_agent_token_admin_blog_agent_tokens_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/blog/agent-tokens/{token_id}":{"delete":{"summary":"Revoke Agent Token","description":"Revoke one blog agent token (any global admin, also an elevated session: revoking removes power).","operationId":"revoke_agent_token_admin_blog_agent_tokens__token_id__delete","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/blog/import":{"post":{"summary":"Import Seed","description":"The frozen seed → the store. Dry run unless the body says `\"dry_run\": false`. Idempotent: a slug\nalready in the store is `exists` (same revision) or `conflict` (other content) and is never\noverwritten. Imported posts are recorded as live (they are live today) with a synthetic\nsyndication go for every channel their block lists (today's PR approval), then\n`blog.store.initialized` once.","operationId":"import_seed_admin_blog_import_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/blog/export":{"get":{"summary":"Export","operationId":"export_admin_blog_export_get","parameters":[{"name":"include_drafts","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Drafts"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/memory/admin/wrap-standalone":{"post":{"summary":"Wrap Standalone","operationId":"wrap_standalone_memory_admin_wrap_standalone_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/library/acquired-copies/membership-report":{"get":{"summary":"Membership Report","operationId":"membership_report_admin_library_acquired_copies_membership_report_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/library/acquired-copies/{user_id}/{cid}/hide":{"post":{"summary":"Hide One","operationId":"hide_one_admin_library_acquired_copies__user_id___cid__hide_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"tenant","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/library/acquired-copies/{user_id}/restore":{"post":{"summary":"Restore","operationId":"restore_admin_library_acquired_copies__user_id__restore_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/library/credential-holds":{"get":{"summary":"List Holds","operationId":"list_holds_admin_library_credential_holds_get","parameters":[{"name":"state","in":"query","required":false,"schema":{"type":"string","default":"held","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/library/credential-holds/release":{"post":{"summary":"Release Hold","operationId":"release_hold_admin_library_credential_holds_release_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/library/credential-holds/delete":{"post":{"summary":"Delete Held","operationId":"delete_held_admin_library_credential_holds_delete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/market/anomalies":{"get":{"summary":"Anomaly Queue","operationId":"anomaly_queue_admin_market_anomalies_get","parameters":[{"name":"all","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"All"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/market/anomalies/review":{"post":{"summary":"Review","operationId":"review_admin_market_anomalies_review_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/market/f1-dryrun":{"get":{"summary":"F1 Dryrun","operationId":"f1_dryrun_admin_market_f1_dryrun_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/marketplace/collections/{cid}/analysis":{"get":{"summary":"Collection Analysis","description":"The latest intent-analysis verdict for a collection (or `null` if none yet). Anonymous-readable\nfor a PUBLIC collection (UX-02): a non-member of the owning tenant sees the verdict only and gets\n404 for a staging/private collection. `?t=` names the item tenant.","operationId":"collection_analysis_marketplace_collections__cid__analysis_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Write Analysis","description":"The operator writes a verdict. Body: {analysis_id, verdict, rationale?, nearest?,\nsuggested_lineage?}. A duplicate/repackage verdict quarantines the collection.","operationId":"write_analysis_marketplace_collections__cid__analysis_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/analysis/queue":{"get":{"summary":"Analysis Queue","description":"Pending analyses (the marketplace-analyst worklist), or `?status=completed|escalated`.","operationId":"analysis_queue_marketplace_analysis_queue_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","default":"","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/analysis/{aid}/escalate":{"post":{"summary":"Escalate Analysis","description":"The operator escalates an ambiguous analysis to a human (records it; the operator raises\nagent.needs_human separately).","operationId":"escalate_analysis_marketplace_analysis__aid__escalate_post","parameters":[{"name":"aid","in":"path","required":true,"schema":{"type":"string","title":"Aid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/collections/{cid}/lineage":{"post":{"summary":"Declare Lineage","description":"The author declares their collection builds on one or more others. Edges start\nUNVERIFIED (shown as \"claimed\") — only a verified edge earns a royalty. #124: gated on the\ncollection's CREDITED AUTHOR (or a tenant admin) — not just tenant publish rights, so a\nco-publisher can't plant claims on another author's collection. Parents must exist (public).","operationId":"declare_lineage_marketplace_collections__cid__lineage_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Lineage","description":"The declared/verified parents and the ACTIVE verified ancestor chain (edges made stale by a\nmajor rewrite are excluded from ancestors and flagged `stale` on the parents), plus `built_on_by`\n— the verified, current, public derivatives that build directly on it (P-03). Anonymous-readable\nfor a PUBLIC collection (UX-02): a non-member of the owning tenant gets 404 for staging/private,\nand sees only parents that are themselves public, without who declared/verified them.","operationId":"get_lineage_marketplace_collections__cid__lineage_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/collections/{cid}/lineage/verify":{"post":{"summary":"Verify Lineage","description":"CONFIRM-ONLY: the analyst (or admin) confirms a build-on edge the author ALREADY DECLARED is\ngenuine (a real delta, not a copy). It cannot author a new edge — an undeclared, self-referential,\nor phantom/private parent is rejected, so verify can't mint a royalty-bearing edge on its own. Only\nverified edges accrue. The deriving collection's current version is pinned so a later MAJOR rewrite\ninvalidates the edge until re-verified. Body: {parent_id, parent_tenant?, parent_version?}.","operationId":"verify_lineage_marketplace_collections__cid__lineage_verify_post","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/collections/{cid}/descendants":{"get":{"summary":"Get Descendants","description":"P-03 \"N built on yours\" — the collections whose `builds_on` edge to this one is currently\nvalid (analyst-verified, not staled by a later major release) and which are themselves live\nPUBLIC listings. Anonymous-readable for a public collection; a non-member gets 404 for a\nstaging/private one (same resolution as `/lineage`, UX-02 / RR01-M04/M06). The list is the\nsame for every viewer — a member of the parent's tenant sees no private derivative either.\n\nQuery: `?t=` owning tenant, `?limit=` (1..100, default 20), `?offset=` (default 0).\nNewest declaration first. Response:\n  {collection_id, tenant, count, limit, offset, next_offset|null,\n   items: [{id, tenant, title, seller, author_handle, version, declared_at, verified_at}]}\n`seller` is the credited author's identity (discovery `owner`), `author_handle` the handle to show.","operationId":"get_descendants_marketplace_collections__cid__descendants_get","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/collections/{cid}/lineage/{ancestor}":{"delete":{"summary":"Undeclare Lineage","description":"MKT-030: the author UNDECLARES a build-on edge they declared (a wrong or withdrawn claim).\n`ancestor` = the parent collection id; `?tenant=` its tenant (default: this collection's).\nSame author gate as declare. Emits `marketplace.lineage.undeclared`; the edge leaves the graph,\nso FUTURE sales accrue nothing to it — past royalty accruals stay untouched as ledger history.\n\nA VERIFIED edge is the analyst's confirmation that the originator is owed a cut; the paying\nderivative's author alone must not drop it (409 `edge_verified`). A global admin may.","operationId":"undeclare_lineage_marketplace_collections__cid__lineage__ancestor__delete","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string","title":"Cid"}},{"name":"ancestor","in":"path","required":true,"schema":{"type":"string","title":"Ancestor"}},{"name":"tenant","in":"query","required":false,"schema":{"type":"string","default":"","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/marketplace/royalties/me":{"get":{"summary":"My Royalties","description":"The caller's royalty balance (accrued / paid / owed) + their ledger entries. A human\nresolves to `author:<handle>` when their tenant credits them, else `tenant:<tenant>`.","operationId":"my_royalties_marketplace_royalties_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/marketplace/royalties/unpaid":{"get":{"summary":"Unpaid Royalties","description":"The payout worklist: every author with a positive owed balance.","operationId":"unpaid_royalties_marketplace_royalties_unpaid_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/marketplace/royalties/payout":{"post":{"summary":"Payout Royalties","description":"Record owed balances as settled out-of-band (v1: no Stripe Connect — no money moves\nhere). Emits an idempotent `marketplace.royalty.payout` marker per (author,currency); the\nledger folds it into `paid`, zeroing `owed`. Body: {dry_run?}. Returns the report, each row\nwith status `recorded_out_of_band` (or `dry_run`).\n\nMKT-033: refused with 409 `lineage_payouts_disabled` while lineage payouts are off\n(billing._LINEAGE_PAYOUTS_ENABLED, off since 2026-09-08) — the historical accruals stay\nledger history and are not paid.","operationId":"payout_royalties_marketplace_royalties_payout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sos/gallery":{"get":{"summary":"Gallery","description":"The pattern + every self-operating service in this tenant with its conformance. An agent key\n(#1231) gets its bound workspace's operators through the agent allow-list only.","operationId":"gallery_sos_gallery_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sos/template":{"get":{"summary":"Template","description":"The first-run template: the chassis kit, file by file, plus the ordered steps.","operationId":"template_sos_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sos/template/{name}":{"get":{"summary":"Template File","operationId":"template_file_sos_template__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/me/terms":{"post":{"summary":"Accept Terms","description":"Record the signed-in human's acceptance of the current Terms. Body {version}; a stale version\nis refused (409 `terms_version_mismatch`) so nobody accepts a text they were not shown.","operationId":"accept_terms_accounts_me_terms_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/me":{"get":{"summary":"Accounts Me","operationId":"accounts_me_accounts_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Delete My Account","description":"Delete the caller's account (GDPR Art. 17). Body: {confirm: <your handle or email>}. Erases:\nOAuth identities, email, name, avatar, handle; every session and this host's library tokens; the\nseller profile of tenants the caller solely owned; memberships (a tenant the caller was the LAST\nowner of is soft-deleted and purged by the reaper after its grace period — incl. the personal\nlibrary); scheduled cancellation of subscriptions; the TEXT of every email we sent them\n(collector/mail — the delivery record survives, the body does not); the handle in item\nattribution/provenance (collector/erasure.py, specs/erasure/v0.1). Retains what\nRETAINED_ON_DELETE lists. Recorded in the erasure ledger so a restore re-applies it.","operationId":"delete_my_account_accounts_me_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/tenants/{tenant_id}/members":{"get":{"summary":"List Members","operationId":"list_members_accounts_tenants__tenant_id__members_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Set Member","description":"Grant/change a user's role in a tenant. Caller must be owner/admin of the tenant\n(or a global admin).\n\nBody `{user_id, role}` changes an existing MEMBER's role (the id comes from the member list);\nfor someone who is not a member yet it is 409 `not_a_member` (RR01-SEC-B05) — except for a\nglobal admin. Body `{email, role}` never grants on the spot (accounts:NF-10): it records a\npending invite and mails a single-use accept link to that address (#987 A, collector/invite_links.py),\nand answers 202 with the same shape whether or not the email belongs to an account (no enumeration).","operationId":"set_member_accounts_tenants__tenant_id__members_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/tenants/{tenant_id}/invites":{"get":{"summary":"List Invites","operationId":"list_invites_accounts_tenants__tenant_id__invites_get","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/tenants/{tenant_id}/invites/{invite_id}":{"delete":{"summary":"Revoke Invite","operationId":"revoke_invite_accounts_tenants__tenant_id__invites__invite_id__delete","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/me/invites":{"get":{"summary":"My Invites","operationId":"my_invites_accounts_me_invites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/invites/{invite_id}/accept":{"post":{"summary":"Accept Invite","description":"#987 A: a matching address only LISTS an invite; it never accepts one. A listed invite answers 409\n`invite_accept_via_link` (with the masked address the link went to); anything else the same 404 as\nbefore. Accepting takes the emailed link: POST /accounts/invite-links/accept, which decides and closes\nthe invite under the same per-invite lock (`InviteStore.locked`) as decline and revoke.","operationId":"accept_invite_accounts_invites__invite_id__accept_post","parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/invites/{invite_id}/decline":{"post":{"summary":"Decline Invite","description":"#987 A review: a matching address never closes an invite either. A former holder whom #990 still\nlists must not be able to decline (and so deny) an invite meant for the address's current holder:\ndeclining takes the emailed link (POST /accounts/invite-links/decline); the inviter or a workspace admin\nrevokes. A listed invite answers 409 `invite_decline_via_link`; anything else the same 404 as before.","operationId":"decline_invite_accounts_invites__invite_id__decline_post","parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/invites/{invite_id}/resend":{"post":{"summary":"Resend Invite Link","description":"#987 A review: the invitee's listing cannot re-send (every re-send kills the live link, so a former\nholder could keep the real mailbox holder from ever using one). Only the inviter or a workspace admin\nre-sends: POST /accounts/tenants/{tenant}/invites/{id}/resend. A listed invite answers 409\n`invite_resend_by_inviter`; anything else the same 404 as before.","operationId":"resend_invite_link_accounts_invites__invite_id__resend_post","parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/tenants/{tenant_id}/invites/{invite_id}/resend":{"post":{"summary":"Admin Resend Invite Link","description":"#987 A: mail a fresh accept link for a pending invite — the inviter while STILL a member of the\nworkspace, or a workspace admin (or a global admin) only (#1007 review: someone removed from the\nworkspace keeps no say over its invites). Body {email}: the invited address, typed again (only its hash\nis stored); it must match the invite (409 `invite_email_mismatch`). Wrong-address guesses are capped per\ninvite and per actor (429, then nothing is checked). Older links of the invite stop working. Sends are\nrate limited per invite, per inviter and per workspace: 429 with `retry_after`.","operationId":"admin_resend_invite_link_accounts_tenants__tenant_id__invites__invite_id__resend_post","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/invite-links/open":{"post":{"summary":"Open Invite Link","description":"Body {t}: the token from the link's fragment. No session needed (the person may still have to sign\nin or up). A valid link answers the invite (workspace, role, expiry) and binds it to this browser\n(HttpOnly cookie, its hash kept server-side) for the sign-in round trip; anything else is 404\n`invite_link_invalid` — the same for an unknown, used, expired or revoked link. Rate limited per\nclient address.","operationId":"open_invite_link_accounts_invite_links_open_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/invite-links/held":{"get":{"summary":"Held Invite Link","description":"The invite this browser opened, and the signed-in account that would join it (so a person signed in\nto the wrong account can switch first), plus that account's current role there, if any. Signed out\n(e.g. right after \"switch account\"), `account` is null: the page asks the person to sign in.","operationId":"held_invite_link_accounts_invite_links_held_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/invite-links/accept":{"post":{"summary":"Accept Invite Link","description":"Accept the invite this browser opened, for the SIGNED-IN account, whatever its e-mail: possession of\nthe link is the proof of mailbox control. Single use; never demotes an existing higher role.","operationId":"accept_invite_link_accounts_invite_links_accept_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/invite-links/decline":{"post":{"summary":"Decline Invite Link","description":"Decline the invite this browser opened. Like accepting, this takes the emailed link (#987 A review):\na former holder whom #990 still lists cannot close an invite meant for the address's current holder.\nNo session needed (whoever has the mailbox may say no without an account). Under the same per-invite\nlock as accept, revoke and supersede; the link is used up and every other link of the invite dies.","operationId":"decline_invite_link_accounts_invite_links_decline_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/invite-links/forget":{"post":{"summary":"Forget Invite Link","description":"\"Not now\": this browser forgets the opened link (the link itself stays usable until it expires).","operationId":"forget_invite_link_accounts_invite_links_forget_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/tenants/{tenant_id}/members/{user_id}":{"delete":{"summary":"Remove Member","operationId":"remove_member_accounts_tenants__tenant_id__members__user_id__delete","parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"string","title":"Tenant Id"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/me/tokens":{"get":{"summary":"My Tokens","description":"The library tokens the caller minted for agents on this host (active + revoked).","operationId":"my_tokens_accounts_me_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Mint My Token","description":"Mint a SCOPED library token for a tool (docs/library-tokens.md). Body:\n{label?, scopes: [\"library:read\"|\"library:publish\"|\"library:acquire\", ...], expires_in_days?}\n(`expires_in_days` 1-365, default 90; every token expires). Needs your own session: a library token\ncan never mint another. The token is returned ONCE; only its hash is stored.","operationId":"mint_my_token_accounts_me_tokens_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/me/tokens/{tid}/revoke":{"post":{"summary":"Revoke My Token","description":"Revoke ONE of the caller's library tokens — or a connected app (an OAuth grant, #777): its\nrefresh tokens and every access token it holds.","operationId":"revoke_my_token_accounts_me_tokens__tid__revoke_post","parameters":[{"name":"tid","in":"path","required":true,"schema":{"type":"string","title":"Tid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/me/sessions":{"get":{"summary":"My Sessions","description":"The caller's signed-in devices (live sessions); `current` marks this one.","operationId":"my_sessions_accounts_me_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/accounts/me/sessions/{sid}/revoke":{"post":{"summary":"Revoke My Session","description":"Sign out ONE device (session) of the caller's — including the current one.","operationId":"revoke_my_session_accounts_me_sessions__sid__revoke_post","parameters":[{"name":"sid","in":"path","required":true,"schema":{"type":"string","title":"Sid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/erase/content":{"post":{"summary":"Erase Content","description":"Irreversibly erase an item's content (all versions, or `versions`). `dry_run` defaults\nto TRUE — a real run needs `dry_run: false` AND `confirm` equal to `<kind>:<id>`.","operationId":"erase_content_admin_erase_content_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/users/{uid}":{"delete":{"summary":"Erase User Admin","description":"Erase a user account for an Art. 17 request that arrived out of band (the user may be\nunable to sign in). Body: {confirm: <uid>, reason?, dry_run?}. Emits `account.deleted` with\nby=\"admin\"; the retained records are listed in the response.","operationId":"erase_user_admin_admin_users__uid__delete","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string","title":"Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/users/{uid}/record-erasure":{"post":{"summary":"Record Removed User Admin","description":"Record the erasure of an account whose record was already removed OUTSIDE the erasure\npath (spec §3.2): tombstone + cleanup of what still links the uid + `account.deleted` +\nthe ledger line. `dry_run` defaults to TRUE — a real run needs `dry_run: false`, `confirm`\nequal to the uid, and a `reason`. `handle` / `trial_email` (optional, from a backup) only\nfeed the keyed hashes and are never stored or echoed.","operationId":"record_removed_user_admin_admin_users__uid__record_erasure_post","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string","title":"Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/erase/mail-legacy-hashes":{"post":{"summary":"Sweep Mail Legacy Hashes","description":"One-shot, idempotent #1010 sweep: strip the legacy plain `body_sha256` from the mail events and\noutbox lines of every ERASED subject. `dry_run` defaults to TRUE (counts + message ids only, no\nwrite); a real run needs `dry_run: false`, `confirm: \"mail-legacy-hashes\"` and a `reason`, which is\nrecorded with the actor and the counts in the global audit log (`erasure.mail_legacy_sweep`).\n`complete: false` means the scan hit its cap: run it again.","operationId":"sweep_mail_legacy_hashes_admin_erase_mail_legacy_hashes_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/admin/erasures":{"get":{"summary":"List Erasures","operationId":"list_erasures_admin_erasures_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/config":{"get":{"summary":"Billing Config","description":"Public billing facts: whether Stripe is wired, whether charges carry VAT (so the UI can word\nprices honestly), the merchant-of-record identity, ToS-consent mode, and the seller terms.\n`lite` (#701) is present only while the Lite tier is offered (AGENT_MDX_LITE_TIER on and a\nPrice configured) — with the flag off this response is exactly what it was.","operationId":"billing_config_billing_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/prices":{"get":{"summary":"List Prices","description":"Configured recurring subscription offerings (metadata only).","operationId":"list_prices_billing_prices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Price","description":"Create (or reconfigure) a recurring Stripe Price for an offering and remember its\nid. Body: {offering, amount_cents, currency?=eur, interval?=month, product_name?}.\noffering is a free-form key, e.g. \"tenant\", \"tenant_custom_name\", \"module:<id>\".","operationId":"create_price_billing_prices_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/offerings":{"get":{"summary":"List Offerings","description":"Marketplace-readable view of the configured subscription offerings (no Stripe price ids), so a\nclient can introspect what is actually purchasable and at what price.","operationId":"list_offerings_billing_offerings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/checkout/{ref}":{"get":{"summary":"Checkout Status","description":"Status of a checkout the caller started — the ONLY source of truth for \"did I pay and get\naccess\" (never the return URL): pending → processing → fulfilled | failed | expired, driven by the\nStripe webhooks (see BillingStore.STATUSES). Scoped: a caller sees only their own intent\n(global-admin sees any).","operationId":"checkout_status_billing_checkout__ref__get","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/checkout/{ref}/returned":{"post":{"summary":"Checkout Returned","description":"The buyer's browser is back from Stripe (the page's <CommerceReturn/> calls this once). Body:\n{outcome: \"success\" | \"cancel\"} — which of the two return URLs it landed on; \"cancel\" is also\nStripe's \"back to merchant\" arrow. Records `funnel.checkout.returned{outcome}` and, for a cancel,\n`funnel.checkout.cancelled`. Changes no checkout state (the webhook stays the source of truth for\npayment); once per ref and outcome. Only the buyer's own checkout (else 404, like the status).","operationId":"checkout_returned_billing_checkout__ref__returned_post","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string","title":"Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/seller/terms":{"get":{"summary":"Get Seller Terms","description":"The seller terms as data (+ an optional worked example for `?list_price_cents=`).","operationId":"get_seller_terms_billing_seller_terms_get","parameters":[{"name":"list_price_cents","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"List Price Cents"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/seller/profile":{"get":{"summary":"Get Seller Profile","description":"The caller-tenant's EU seller onboarding profile (owner view: bank/tax identifiers MASKED)\n+ Connect status incl. what Stripe still requires + the seller terms.","operationId":"get_seller_profile_billing_seller_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Set Seller Profile","description":"Capture/update the seller's EU onboarding profile — the DAC7/PStTG identity set + EEA address\n+ VAT status + payout IBAN (+ DOB/TIN for individuals, registration number + beneficial owners for\nbusinesses). EEA sellers only. Recorded now because DAC7 fields cannot be back-filled; it gates\npaid listing once onboarding enforcement is on. Does NOT create a Stripe account.\n\nThe profile is stored in the seller-PII vault; the event log only gets a redacted change record\n(field names, country, IBAN last-4). An absent or masked `iban` means \"keep the stored one\".","operationId":"set_seller_profile_billing_seller_profile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"summary":"Delete Seller Profile","description":"Erase the tenant's seller profile (owner/admin). Bank + identity data leave every read path\nimmediately; when the seller had sales the identity stays in the sealed vault until the 10-year\ntax retention ends (§14b UStG / §147 AO / §26 PStTG) and is then purged. Payout onboarding has to\nbe redone to sell again.","operationId":"delete_seller_profile_billing_seller_profile_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/vat-checks/retry":{"post":{"summary":"Retry Vat Checks","description":"#904: re-run every due VIES check now (pending ones past their retry time). Global admin.","operationId":"retry_vat_checks_billing_seller_vat_checks_retry_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/profiles/redact-log":{"post":{"summary":"Redact Seller Log","description":"Global admin: rewrite LEGACY `seller.profile.updated` events (full profile in the payload)\ninto redacted change records, in place, in the default event log — after migrating each profile\ninto the vault. Body {dry_run?=true}. Reindexes the SQLite index + entity projections.","operationId":"redact_seller_log_billing_seller_profiles_redact_log_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/connect/account-link":{"post":{"summary":"Connect Account Link","description":"Create (or reuse) the seller's Stripe Express Connect account and return a hosted onboarding\nlink. EEA only; funds are HELD (no payouts until WS-H). Needs a completed profile and Stripe\nConnect enabled on the platform (flag). Returns the seller to `/sell?connect=done|refresh#payouts`\non THEIR origin (UX-08: Payouts live on the Sell page).","operationId":"connect_account_link_billing_connect_account_link_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/balance":{"get":{"summary":"Seller Balance","description":"The caller-tenant's payable balance: accrued / on-hold (in reserve) / available / paid — with\nthe terms that explain the numbers and where the self-billing documents are. The workspace\nbalance is the owner's/admin's; a member gets `balance: null` and buckets over their own\nlistings' lines only (`money_scope: \"own_listings\"`).","operationId":"seller_balance_billing_seller_balance_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/listings":{"get":{"summary":"Seller Listings","description":"The caller-tenant's money PER LISTING, from the same ledger as the balance: `sales` (every\nsale), `refunded` (sales with any refund), `fully_refunded`, `earned` (the seller's share after\nVAT, the commission and refunds — partial refunds pro rata), `on_hold` (still in the reserve) and\n`gross` (what buyers paid incl. VAT, after refunds — context, not the seller's money). Per\ncurrency, minor units. No buyer identities.","operationId":"seller_listings_billing_seller_listings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/statement":{"get":{"summary":"Seller Statement","description":"The caller-tenant's statement (Sell Phase 2): every sale, refund and payout from the payout\nledger, with date, listing, version, gross, VAT, platform fee and the seller's amount — integer\ncents per line with its currency, never recomputed. `?month=YYYY-MM` filters by the line's date\n(UTC), `?kind=&id=` to one listing, `?format=csv` returns the same lines as a download. Same\nauthz as /billing/seller/*: always the HOST workspace's own books (there is no tenant\nparameter); a non-member gets 403. Owner/admin: every line of the workspace. A plain member: only\nthe sales and refunds of the listings they authored, totals and buckets over just those lines,\npayouts (the workspace's) None. No buyer identity in either form.","operationId":"seller_statement_billing_seller_statement_get","parameters":[{"name":"month","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Month"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/seller/performance":{"get":{"summary":"Seller Performance","description":"One listing's performance (Sell Phase 3), for the HOST workspace's own listing only (same\nauthz as /billing/seller/*; there is no tenant parameter — a listing of another workspace is a\n404). Totals (views all-time, free acquisitions, sales, refunds, rating with count, earned net\nfrom the ledger), conversion (fraction always, percentage at n >= 30 views), a 12-week series\nfrom the ledger dates, a per-version table and a recent-activity list. No buyer identity.","operationId":"seller_performance_billing_seller_performance_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","default":"collection","title":"Kind"}},{"name":"id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/seller/overview":{"get":{"summary":"Seller Overview","description":"The seller's compact overview (Sell Phase 3), the HOST workspace's own books: this month vs\nlast month (UTC calendar months; sales, refunds, earned net), the top listings by earnings and\nthe all-time totals — all from the payout ledger lines the statement shows. No buyer identity.","operationId":"seller_overview_billing_seller_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/seller/documents":{"get":{"summary":"Seller Documents","description":"The tenant's self-billing documents (SB-…): one per payout transfer, issued by crossVault on the\nseller's behalf. `/billing/invoices` lists BUYER documents (subject user:…); these carry\nsubject tenant:<t> and were unreachable before. Issued to the WORKSPACE (one per transfer, not\nper listing or author), so owner/admin only.","operationId":"seller_documents_billing_seller_documents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/payouts/unpaid":{"get":{"summary":"Payouts Unpaid","description":"Admin payout worklist: sellers with a cleared, unpaid balance, annotated with KYC readiness.","operationId":"payouts_unpaid_billing_payouts_unpaid_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/payouts/corrections/sweep":{"post":{"summary":"Payouts Corrections Sweep","description":"Issue every correcting Gutschrift (#922) still missing, e.g. after an issuance failed.\nIdempotent. Not gated on `AGENT_MDX_PAYOUTS`: corrections only exist for payouts already sent, and\nmust still be issued if payouts were switched off since.","operationId":"payouts_corrections_sweep_billing_payouts_corrections_sweep_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/payouts/run":{"post":{"summary":"Payouts Run","description":"Sweep cleared balances to sellers via Stripe Connect transfers (separate charges + transfers).\nGated: KYC/payouts-enabled + a Connect account + past the reserve window. WP-13: each payout is\nrecorded as an intent BEFORE Stripe is called and sent with a deterministic Idempotency-Key\n(`agent-mdx:payout:<tenant>:<cur>-<seq>`); open intents from an earlier run are retried first\nwith their stored key. One run at a time (409 `payout_run_in_progress`); per-payout leases on\ntop. Emits marketplace.seller.payout (deduped on the Stripe transfer id) and ONE self-billing\ndocument per transfer. Body: {dry_run?}. OFF until `AGENT_MDX_PAYOUTS=on`; with\n`AGENT_MDX_PAYOUTS=dry` only `{\"dry_run\": true}` is accepted (#1279 G2).","operationId":"payouts_run_billing_payouts_run_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/payouts/cycle/clear":{"post":{"summary":"Payout Cycle Clear","description":"#1365: lift the HOLD of a scheduled monthly cycle (global admin). Body: {month \"YYYY-MM\",\nreason, mode? (\"on\", default | \"dry\")}. A scheduled real cycle that started but did not finish\n(an idempotency conflict, an exception, a crash mid-run) holds its month: the scheduler runs\nnothing more that month — no hourly re-run that would pay sellers who newly reach the minimum —\nuntil this clears it. After the clear the NEXT tick runs that month's cycle again (a full run).\nClear only once the cause is fixed; the alternative is to leave the hold and run\n`POST /billing/payouts/run` by hand (which never counts as the month's cycle). Emits\n`marketplace.seller.payout_cycle_cleared` {month, mode, reason, by}. 404 `no_cycle_hold` when\nthe month has none; 409 `cycle_already_done` when the month's cycle finished; 409\n`payout_run_in_progress` while a payout run holds the run lock — the clear itself runs under that\nlock, so it can never drop the `started` hold of a run that is still in flight.","operationId":"payout_cycle_clear_billing_payouts_cycle_clear_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/payouts/intents/close":{"post":{"summary":"Payout Intent Close","description":"Close a stuck payout intent (global admin). Body: {tenant, payout_id, action, reason,\ntransfer_id?}.\n\n  link     the transfer EXISTS at Stripe (`transfer_id`, read by GET /transfers/{id}). It must be\n           PROVABLY this intent's: its `transfer_group` equals the intent's, or its\n           `metadata.payout_id` AND `metadata.tenant` name this intent — a same-amount transfer\n           of another payout line is refused (`transfer_not_this_intent`), as is a transfer\n           already booked/linked anywhere in the ledger (`transfer_already_booked`). Plus same\n           destination, amount and currency. Then book it — one SB + the payout event — and close.\n  abandon  no transfer exists: close with a required `reason`. Refused when the intent has no\n           transfer_group (cannot be verified at Stripe), while the transfer_group lookup finds a\n           transfer (link it instead) or when it cannot be done. The held amount goes back to the\n           seller's payable balance; the next run pays it under a new seq.\n\nNOT gated on `AGENT_MDX_PAYOUTS` (#1279 G2): a close never creates a transfer (link books one\nthat already exists at Stripe, abandon proves none exists), and after a rollback (payouts\nswitched off with intents still open) the admin must still be able to clean them up. Still 409\n`self_billing_wording_pending` in live mode while the D4 note is a placeholder (link issues an SB).\n\nEmits `marketplace.seller.payout_intent_closed` {tenant, payout_id, outcome, reason, by,\ntransfer_id}. Idempotent: closing an already-closed intent the same way returns it unchanged\n(`already_closed`); a different close is 409. Takes the payout run lock (409 while a run is on).","operationId":"payout_intent_close_billing_payouts_intents_close_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/invoices":{"get":{"summary":"My Invoices","description":"The caller's own VAT invoices + credit notes — their durable purchase records (WS-E).\nThe buyer can retrieve and save these; each row links to its rendered §14 document.","operationId":"my_invoices_billing_invoices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/invoices/{number}":{"get":{"summary":"Invoice Document","description":"One billing document rendered with the §14 UStG fields (see render_document). The buyer sees\ntheir own INV/CN; a tenant member sees the tenant's SB documents. `?include=stripe` also fetches\nthe Stripe-hosted invoice URL/PDF (needs the Invoices:read key permission).","operationId":"invoice_document_billing_invoices__number__get","parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"string","title":"Number"}},{"name":"include","in":"query","required":false,"schema":{"type":"string","default":"","title":"Include"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/invoices/{number}/legal":{"get":{"summary":"Legal Invoice","description":"O-5: the LEGAL invoice behind a journal entry — a redirect to the Stripe-hosted invoice (or its\ncredit note, for a CN- entry that has one). Same access rule as the journal entry itself. 404 when\nno Stripe document is linked; 502 when Stripe cannot be reached (the entry stays readable).","operationId":"legal_invoice_billing_invoices__number__legal_get","parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"string","title":"Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/documents/{number}/void":{"post":{"summary":"Void Document","description":"Void an ISSUED journal document (global admin). Event-sourced (`billing.document.voided`): the\ndocument and its number stay in the register and the GoBD export, annotated with the void record —\nnothing is deleted or renumbered. Deliberately narrow: only a document of a synthetic QA buyer\n(`reason_code: qa_test_document`, e.g. the historic INV-000001 / CN-000001, O-5) — a real sale is\ncorrected by a credit note, never voided. Idempotent: a second void of the same number is a no-op.\nBody: {reason_code: \"qa_test_document\", reason: \"<free text for the record>\", dry_run?}.","operationId":"void_document_billing_documents__number__void_post","parameters":[{"name":"number","in":"path","required":true,"schema":{"type":"string","title":"Number"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing/documents/number-void":{"post":{"summary":"Void Unused Number","description":"Record a GAP in a document series by hand (global admin): a number that the register reports\nas missing (GET /reports/document-gaps) and no document uses. Refuses a used number. Body:\n{number, kind, reason}.","operationId":"void_unused_number_billing_documents_number_void_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/checkout":{"post":{"summary":"Checkout","description":"Start a Stripe Checkout (see `_checkout`). Every refusal before a checkout exists is recorded\nas `funnel.checkout.gate_refused{code: <the error code>}` — throttled per person and gate, so a\nretrying client is one event a minute plus a count.","operationId":"checkout_billing_checkout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/subscriptions":{"get":{"summary":"My Subscriptions","description":"The logged-in human's subscription checkouts and their lifecycle facts.","operationId":"my_subscriptions_billing_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/subscriptions/cancel":{"post":{"summary":"Cancel Subscription","description":"The §312k \"Verträge hier kündigen\" action: cancel the caller's subscription at the end of the\ncurrent period. Body {ref} (from /billing/subscriptions). Returns the confirmation the law wants\nshown immediately (what was cancelled, effective when). [[NEEDS OWNER]]: email confirmation.","operationId":"cancel_subscription_billing_subscriptions_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/webhook":{"post":{"summary":"Webhook","description":"Stripe webhook. Verifies the signature, then on `checkout.session.completed`\nfulfils the stored intent (entitlement for items; owner membership for tenants).\nIdempotent per Stripe event id.\n\nStatus contract (what Stripe sees — docs/go-live-eu-marketplace-runbook.md):\n  - 400 `bad_signature` ONLY for a delivery whose signature does not verify (details.reason:\n    missing_header | malformed_header | timestamp_outside_tolerance | no_matching_secret);\n  - 400 `bad_payload` for a verified body that is not a JSON object (Stripe never sends one);\n  - 503 `webhook_unconfigured` / `billing_unavailable` when WE cannot verify or record yet —\n    Stripe retries, and the log no longer blames a signature that was never checked;\n  - 200 for every verified event, including types we do not handle, thin (v2) events, events\n    from the other Stripe mode, duplicates and events for a checkout we do not know;\n  - 5xx when fulfilment itself fails, so Stripe redelivers.","operationId":"webhook_billing_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/admin/test-mode-grants":{"get":{"summary":"Test Mode Grants","description":"DRY-RUN cutover report (WP-DE-14 e): fulfilled, NON-QA intents whose Stripe ids are not\npositively live (test-mode or unknown = pre-cutover). Test money is not a purchase, so the\nOPERATOR decides per row whether to revoke the grant (with a short notice). Nothing is changed.","operationId":"test_mode_grants_billing_admin_test_mode_grants_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/admin/router-usage/seal":{"post":{"summary":"Router Usage Seal","description":"Seal closed months of the router usage ledger on demand (the daily overage sweep does it\ntoo) — including a BACKFILL of already-closed months. Body: {month?, tenant?, dry_run?}.\nIdempotent: a sealed (month, tenant) reports `already_sealed` and is never re-sealed; change\none only via /billing/admin/router-usage/correct. See collector/store/usage_seals.py.","operationId":"router_usage_seal_billing_admin_router_usage_seal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/admin/router-usage/correct":{"post":{"summary":"Router Usage Correct","description":"Explicit correction of a sealed month from the raw router.usage events still in the log.\nBody: {month, tenant, reason, dry_run?}. 409 not_sealed / raw_events_unavailable / no_change.","operationId":"router_usage_correct_billing_admin_router_usage_correct_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/intents/reconcile":{"post":{"summary":"Reconcile Intents","description":"Settle `pending` intents that never heard a webhook (WP-6): one-time checkouts after\nAGENT_MDX_RECONCILE_ONE_TIME_AGE_S (default 15 min; the same pass also runs every 5 min as\n`reconcile_sweep_loop`), subscription checkouts after 24 h. Body {dry_run}\n(default TRUE — pass false to apply). QA intents are skipped. With a session id: read the session\nfrom Stripe (GET only; the one write is the O-3 geo refund the replayed webhook path issues for a\nbuyer outside the EU) — `expired` → expired, `complete` → replayed as the\nmissed `checkout.session.completed` (same idempotent path as the webhook). Without one: the\nsessions created around the intent are listed first (`_find_session_for`); a match is handled\nlike a stored session id, and only when Stripe positively has none is the intent expired with\nreason `never_reached_stripe`. Stripe unreadable → skip. Re-running is a no-op.\nSUBSCRIPTION intents stuck in `processing` for 15 min+ are recovered too\n(`_reconcile_processing_subscription`): the Subscription is read and, when active/trialing and\nin the platform's Stripe mode, granted through the webhook's own `_apply_subscription`.","operationId":"reconcile_intents_billing_intents_reconcile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/portal":{"get":{"summary":"Portal","description":"Stripe billing portal link for the logged-in human to manage/cancel their sub. Returns to\n`/account?portal=done` on the origin the request came from.","operationId":"portal_billing_portal_get","parameters":[{"name":"return_to","in":"query","required":false,"schema":{"type":"string","default":"","title":"Return To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/billing/payment-methods":{"get":{"summary":"Payment Methods","operationId":"payment_methods_admin_billing_payment_methods_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/billing/withdrawals":{"get":{"summary":"List Withdrawals","operationId":"list_withdrawals_billing_withdrawals_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Declare Withdrawal","description":"The \"Widerruf bestätigen\" step. Body {ref, confirm: true, name?, email?}; signed out, name and\nemail are required. Returns 201 with the receipt facts (what was declared, when received).","operationId":"declare_withdrawal_billing_withdrawals_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/reports/tax-liability":{"get":{"summary":"Tax Liability","description":"Net VAT owed per (currency, country, rate, quarter), after refunds. EU rows (in_eu_oss=true)\nfeed the OSS return; non-EU country rows show where a foreign consumption tax may be due.\n\n`jurisdiction_counters` (#1326, report-only): per year, buyer country, US state\n(`region`, where known) and currency, the gross amount and the transaction count of paid orders,\nrefunds apart — what foreign registration thresholds test. For the year of `quarter` when given.\nThe country is the one the checkout's billing record holds (`buyer_geo`); `unknown` when neither\nit nor the payment event has one.\n\n`eu_b2c_threshold` (#618): the calendar-year net revenue from consumers in EU member states other\nthan DE, against the EUR 10,000 limit of § 3a (5) UStG, for the current and the previous\nEurope/Berlin year (always the years around today, whatever `quarter` says). Recomputed from the\nbilling events on every read; the rules are in collector/eu_b2c_threshold.py.\n\n`vat_evidence` (#1411 R-3, report-only): for `quarter` (or all), how many booked sales carry ONE\nlocation-evidence item, two or more CONSISTENT ones (one of them third-party), agreeing but only\nself-declared ones (`self_declared_only`), or CONFLICTING ones, the sales without a block\n(`not_recorded`: before the change or with AGENT_MDX_VAT_LOCATION_EVIDENCE off), those with a\nthird-party item, those whose re-read disagreed (`with_reread_conflict`) and the count per\npayment method type. The billing record's block wins over the sale event's copy. Counts only; the per-sale block (country codes, never an IP) is\non each `billing.payment.succeeded` payload, so `GET /reports/gobd-export` carries it per sale.","operationId":"tax_liability_reports_tax_liability_get","parameters":[{"name":"quarter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quarter"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reports/dac7":{"get":{"summary":"Dac7","description":"DAC7/PStTG worksheet: per-seller consideration + count by quarter, joined with the reportable\nidentity captured at onboarding. Sellers with transactions but no profile are flagged (a data gap\nthe onboarding gate is meant to prevent). First-party sales (the platform's own workspace, O-4)\nare platform revenue, not a seller's, and never appear here.","operationId":"dac7_reports_dac7_get","parameters":[{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reports/ledger":{"get":{"summary":"Ledger","description":"Revenue totals per currency + the booked invariant Σnet+Σvat==Σgross, plus document counts.\n`payouts` splits the net into seller accruals, the commission (`platform_cut`) and first-party\nsales (`first_party_net`, O-4); `platform_revenue` = commission + first-party.","operationId":"ledger_reports_ledger_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/reports/self-billing-vat":{"get":{"summary":"Self Billing Vat Report","description":"The VAT figures from the Gutschriften (SB-) of a period (`YYYY-MM`, `YYYY-Qn` or `YYYY`, on the\nEurope/Berlin calendar) for the VAT pre-return (#906, #922): per seller VAT status — Σ net, Σ input\nVAT (19 % on top for DE sellers taxed normally), Σ § 13b (1) and § 13b (2) base and tax,\nΣ § 19 amounts — and EUR figures per row and in total (`POST /reports/fx-rates` records the rate\nof a non-EUR currency). `format=csv` returns one row per document.","operationId":"self_billing_vat_report_reports_self_billing_vat_get","parameters":[{"name":"period","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Period"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reports/fx-rates":{"get":{"summary":"Fx Rates List","description":"The EUR conversion rates the VAT export uses (#922), per currency and month.","operationId":"fx_rates_list_reports_fx_rates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Fx Rate Record","description":"Record the EUR rate of a non-EUR currency for one month (#922) as an append-only event. Body:\n{currency (ISO 4217, not EUR), month (YYYY-MM), rate (foreign units per 1 EUR, > 0), source\n(required — where the rate is from, e.g. the official monthly table)}.\n\nA recorded rate is immutable: a second record for the same month is refused (409 `rate_exists`)\nunless it says `supersedes: true` with a `reason` — then it is recorded with the rate it replaces,\nand a `billing.fx_rate.superseded` audit event is written. The export flags every row converted\nat a superseded rate (`eur_rate_superseded`, `superseded_rates`): an export taken before may differ.","operationId":"fx_rate_record_reports_fx_rates_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/reports/credit-notes":{"get":{"summary":"Credit Notes","description":"The invoice + credit-note register (kind: 'invoice' | 'credit_note' | omit for both).","operationId":"credit_notes_reports_credit_notes_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reports/document-gaps":{"get":{"summary":"Document Gaps","description":"Per series prefix: numbers below the highest issued one that no document and no\n`billing.document.number_voided` record explains (record one with POST\n/billing/documents/number-void), plus the unused-number and void records themselves.","operationId":"document_gaps_reports_document_gaps_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/reports/gobd-export":{"get":{"summary":"Gobd Export","description":"A dated dump over [since, until] (ISO dates, inclusive-ish string compare): the document\nregister (journal entries, reversal entries, self-bills — voided ones included, annotated), the\nvoid and unused-number records, the open number gaps, the tax-liability rows, and the raw billing\nevents (`_GOBD_EVENTS`), cut from the event log. `since`/`until` filter the raw events by\ntimestamp. The log is append-only by convention, fsynced and backed up — not tamper-evident;\n`integrity` in the response says exactly that.\n\n`vat_evidence` (#1411 R-3): per sale in range, its location-evidence block AS OF `until` (now,\nwithout one) and its trail of changes up to then (`vat_evidence_trail`); changes after `until`\nsit apart in `after_range`, marked and timestamped. A block filled or contradicted after booking\nis never shown only as the original failed read. With AGENT_MDX_VAT_LOCATION_EVIDENCE off (no\nblocks) the key is an empty list.","operationId":"gobd_export_reports_gobd_export_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Until"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/access":{"get":{"summary":"My Access","description":"The caller's disclosure levels — lets the UI hide per-user views from an aggregate-only\ncredential instead of letting it hit 403s — and its Support-desk capability (`support`). A\nsigned-in person holding only a Support-desk role gets `kind: \"support\"`, no analytics level.\nEvery answer is computed from the role registry on this request (nothing cached).","operationId":"my_access_platform_access_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response My Access Platform Access Get"}}}}}}},"/platform/roles":{"get":{"summary":"List Roles","operationId":"list_roles_platform_roles_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Roles Platform Roles Get"}}}}}},"post":{"summary":"Grant Role","description":"Grant a platform role to a signed-in USER. Only a user id is accepted — a machine token,\na producer or a token owner cannot hold a platform role (400 `human_only_role`).","operationId":"grant_role_platform_roles_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/platform/roles/{user_id}/{role}":{"delete":{"summary":"Revoke Role","operationId":"revoke_role_platform_roles__user_id___role__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}},{"name":"role","in":"path","required":true,"schema":{"type":"string","title":"Role"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Role Platform Roles  User Id   Role  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/reveal":{"post":{"summary":"Reveal","description":"Reveal ONE record: body `{resource, id, reason}`. The access is written to the audit\n(`admin.analytics.accessed`, without the value) before the value is returned.","operationId":"reveal_platform_reveal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reveal Platform Reveal Post"}}}}}}},"/platform/access-audit":{"get":{"summary":"Access Audit","description":"Recent `admin.analytics.accessed` events, newest first. Global admin only.","operationId":"access_audit_platform_access_audit_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"who","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Who"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Access Audit Platform Access Audit Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/kpi/qda":{"get":{"summary":"Kpi Qda","description":"QDA-28 — Qualified Delivered Acquisitions per 28 days (specs/platform-analytics/v0.1 § 7).\nL1: counts only — the rolling-28-day total with the paid 3rd-party / free 3rd-party /\nfirst-party split, all-time qualifying pairs, the excluded counts (own / test / refunded)\nand a weekly trend. Read-only; computed from the event log on request.","operationId":"kpi_qda_platform_kpi_qda_get","parameters":[{"name":"weeks","in":"query","required":false,"schema":{"type":"integer","maximum":52,"minimum":0,"default":12,"title":"Weeks"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Kpi Qda Platform Kpi Qda Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/analytics/web":{"get":{"summary":"Analytics Web","description":"Website page loads and the unique-visitor estimate per Europe/Berlin day, top pages, referrer\ndomains, UTM campaigns and the sign-up / first save / first purchase funnel as independent daily\ncounts. L1 aggregates; every read is written to the access audit (fail-closed) first.","operationId":"analytics_web_platform_analytics_web_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/signup-sources":{"get":{"summary":"Signup Sources","description":"The optional sign-up answers in AGGREGATE (signup_source.answers): counts per normalised\nanswer, an answer given by fewer than 5 accounts folded into `other`, small counts as \"<5\"; no\nday, account id, handle or e-mail; test accounts left out. GLOBAL ADMIN only (a platform analyst\ngets 403): the answers are free text people typed. Every read is written to the access audit\n(fail-closed) first.","operationId":"signup_sources_platform_signup_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/platform/kpi/storefront":{"get":{"summary":"Storefront","description":"Page views per page type and day (human / bot), listing detail views per listing and day\n(human), external referrer domains (human page loads) and the bot share.","operationId":"storefront_platform_kpi_storefront_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/kpi/cli":{"get":{"summary":"Cli","description":"Installer and CLI-file downloads per day and channel, and the a4sx CLI versions delivered.\n\nthe a4sx CLI sends no version header and no telemetry (owner D2), so \"adoption\" is what the server\nDELIVERED: each `GET /cli/<CLI_NAME>.py` or `GET /cli/amdx.py` (same file) counts the `__version__` of the file served, by channel —\n`installer` (curl/wget, the `curl … | sh` path), `self_update` (`a4sx update`), `browser`,\n`other`. Bots are counted apart and are not part of the adoption figures.","operationId":"cli_platform_kpi_cli_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/kpi/agents":{"get":{"summary":"Agents","description":"Agent & plugin usage (collector/agent_usage_kpi.py, #1234 phase 1): MCP tool calls per tool and\nclient name, MCP consents (approved / denied) and sign-ins per client kind, CLI requests per CLI\nversion and /orient reads, per Europe/Berlin day. L1 aggregates; every read is written to the\naccess audit (fail-closed) first, as for /platform/analytics/web.","operationId":"agents_platform_kpi_agents_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/kpi/overview":{"get":{"summary":"Kpi Overview","description":"North star QDA-28, the input metrics computable today and the guardrails — L1.","operationId":"kpi_overview_platform_kpi_overview_get","parameters":[{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/people":{"get":{"summary":"People","operationId":"people_platform_people_get","parameters":[{"name":"level","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Level"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/workspaces":{"get":{"summary":"Workspaces","operationId":"workspaces_platform_workspaces_get","parameters":[{"name":"level","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Level"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/commerce":{"get":{"tags":["platform"],"summary":"Commerce","operationId":"commerce_platform_commerce_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/commerce/purchases":{"get":{"tags":["platform"],"summary":"Commerce Purchases","description":"L2 list. The access is audited (one `admin.analytics.accessed` per request) BEFORE the rows\nare computed; a failed audit write fails the request.","operationId":"commerce_purchases_platform_commerce_purchases_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/funnels":{"get":{"tags":["platform"],"summary":"Funnels","operationId":"funnels_platform_funnels_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/funnels/revenue":{"get":{"tags":["platform"],"summary":"Revenue Funnel","description":"The revenue funnel (collector/platform_revenue.py). L1 counts only. It also reads the web and\nagent-usage day tallies, so every read is written to the access audit (fail-closed) first, as\nfor /platform/analytics/web and /platform/kpi/agents.","operationId":"revenue_funnel_platform_funnels_revenue_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(month|week)$","default":"month","title":"Period"}},{"name":"weeks","in":"query","required":false,"schema":{"type":"integer","maximum":52,"minimum":1,"default":12,"title":"Weeks"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/modules":{"get":{"tags":["platform"],"summary":"Modules","operationId":"modules_platform_modules_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/cost-items":{"get":{"tags":["platform"],"summary":"Cost Items","description":"The owner's operating cost items, priced for this month exactly as the margin prices them\n(real usage for a usage-sourced prepaid credit, capped at the credit). L1: platform figures;\nwho changed an item (`updated_by`) only for a global admin.","operationId":"cost_items_platform_cost_items_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/platform/cost-items/{item_id}":{"put":{"tags":["platform"],"summary":"Put Cost Item","description":"Create an item, or change one from a month on (global admin). Body: the item, plus optional\n`from` (YYYY-MM, default the current Berlin month, never earlier: 422 `from_in_past`) — the first\nmonth the new figures apply; earlier months keep the old ones. The one way to change a past\nmonth is an explicit correction: `correction: true` + `reason` (recorded on the event). A `credential` link must name a fleet credential that\ncarries a cost (422 `unknown_credential`). 201 on create, 200 on change.","operationId":"put_cost_item_platform_cost_items__item_id__put","parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["platform"],"summary":"Delete Cost Item","description":"End one item (global admin): it still counts in the current Berlin month and stops counting\nfrom the next one; past months are untouched and the item stays listed as ended.","operationId":"delete_cost_item_platform_cost_items__item_id__delete","parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/platform/sellers":{"get":{"tags":["platform"],"summary":"Sellers","operationId":"sellers_platform_sellers_get","parameters":[{"name":"months","in":"query","required":false,"schema":{"type":"integer","maximum":24,"minimum":1,"default":12,"title":"Months"}},{"name":"include_test","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Test"}},{"name":"window_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":7,"default":90,"title":"Window Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bundles":{"get":{"summary":"List Bundles","operationId":"list_bundles_bundles_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Bundle","description":"Create a named bundle from items you can access. Body: {name, items:[{kind,id,tenant?}]}.","operationId":"create_bundle_bundles_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/bundles/{bundle_id}":{"get":{"summary":"Get Bundle","operationId":"get_bundle_bundles__bundle_id__get","parameters":[{"name":"bundle_id","in":"path","required":true,"schema":{"type":"string","title":"Bundle Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Update Bundle","description":"Rename and/or replace the item set (re-validates access).","operationId":"update_bundle_bundles__bundle_id__post","parameters":[{"name":"bundle_id","in":"path","required":true,"schema":{"type":"string","title":"Bundle Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Bundle","operationId":"delete_bundle_bundles__bundle_id__delete","parameters":[{"name":"bundle_id","in":"path","required":true,"schema":{"type":"string","title":"Bundle Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bundles/{bundle_id}/hydrate":{"get":{"summary":"Hydrate Bundle","description":"Everything needed to seed a fresh session in ONE call: each accessible member\nresolved to the newest version the caller may have (latest, or for a paid/private item the\nnewest in a major line they hold) with file bytes (base64). Access is re-checked per member\nat hydrate time; a member the caller can no longer access returns a stub.","operationId":"hydrate_bundle_bundles__bundle_id__hydrate_get","parameters":[{"name":"bundle_id","in":"path","required":true,"schema":{"type":"string","title":"Bundle Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/orient":{"get":{"summary":"Orient","description":"Whoami-prepended orientation. An ANONYMOUS caller (no/invalid token) still gets the public\nmarketplace brief — this is the onboarding entry point for a brand-new user whose agent hasn't\nsigned in yet, so it must never 401. A marketplace-only caller (signed-in human with no tenant,\nor a catalog-scoped agent) gets the same brief with a real whoami; a tenant member gets the full\nspec. `?topic=` selects a section of the brief; an unknown or empty topic falls back to the\ncore brief, so a wrong guess costs a round-trip and never a 404. Hardened: a spec-serve or\nhint-write failure degrades to the brief, never a 5xx.","operationId":"orient_orient_get","parameters":[{"name":"topic","in":"query","required":false,"schema":{"type":"string","default":"","title":"Topic"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/polaris-baselines":{"get":{"summary":"List Baselines","description":"Index: every service with a baseline + its source_ref + content_hash.","operationId":"list_baselines_polaris_baselines_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/polaris-baselines/{service}":{"get":{"summary":"Get Baseline Manifest","description":"Return the manifest record for a service's current baseline.","operationId":"get_baseline_manifest_polaris_baselines__service__get","parameters":[{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/polaris-baselines/{service}/{filename}":{"get":{"summary":"Get Baseline File","description":"Return the body of a served baseline file. spec.yaml is returned as\nraw bytes (verbatim) to preserve YAML anchors; never re-serialized.","operationId":"get_baseline_file_polaris_baselines__service___filename__get","parameters":[{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/authz/migration":{"get":{"summary":"Migration Plan","description":"Dry-run seed+audit plan. No writes — review before POSTing apply.","operationId":"migration_plan_authz_migration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Migration Plan Authz Migration Get"}}}}}}},"/authz/migration/apply":{"post":{"summary":"Migration Apply","description":"Apply the seed+audit plan: write capability_roles + emits onto manifests.","operationId":"migration_apply_authz_migration_apply_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Migration Apply Authz Migration Apply Post"}}}}}}},"/authz/token-migration":{"get":{"summary":"Token Migration Worklist","description":"Dry-run: every active legacy emit/read token + its ge_tok_ successor\nstatus. No writes.","operationId":"token_migration_worklist_authz_token_migration_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Token Migration Worklist Authz Token Migration Get"}}}}}}},"/authz/token-migration/apply":{"post":{"summary":"Token Migration Apply","description":"Mint a ge_tok_ replacement for ONE legacy token (plaintext returned\nonce). Stamps superseded_by on the legacy record; does NOT revoke it.","operationId":"token_migration_apply_authz_token_migration_apply_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenMigrationApplyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Token Migration Apply Authz Token Migration Apply Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/authz/token-migration/backfill-expiry":{"post":{"summary":"Token Migration Backfill Expiry","description":"S-45 one-off: copy `expires_at` from the `migrated_from` source onto migrated ge_tok_\ntokens that have none (pre-S-45 migration dropped it). DRY-RUN unless `{\"apply\": true}`.","operationId":"token_migration_backfill_expiry_authz_token_migration_backfill_expiry_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TokenExpiryBackfillRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Token Migration Backfill Expiry Authz Token Migration Backfill Expiry Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/authz/enforcement":{"get":{"summary":"List Enforcement","description":"Every topic with an explicit enforcement mode. Topics not listed default\nto ``shadow`` (record-only; PR-4 behaviour).","operationId":"list_enforcement_authz_enforcement_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Enforcement Authz Enforcement Get"}}}}}}},"/authz/enforcement/{topic}":{"post":{"summary":"Set Enforcement","description":"Flip a topic's emit-enforcement mode (admin-only). ``enforced`` makes a\nwould-deny emit on that topic actually 403 (forbidden_emit); ``shadow``\nrolls it back to record-only. Idempotent last-write-wins.\n\nBreak-glass #5 pre-flight: refuse to flip a topic to ``enforced`` if there\nis NO working admin path (would risk locking authz changes out). Flipping\nBACK to ``shadow`` is always allowed — it can only ever relax enforcement,\nso it must never be blocked (it's the rollback lever).","operationId":"set_enforcement_authz_enforcement__topic__post","parameters":[{"name":"topic","in":"path","required":true,"schema":{"type":"string","title":"Topic"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthzEnforcementRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Enforcement Authz Enforcement  Topic  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/unseal":{"post":{"summary":"Vault Unseal","description":"Operator route: present the master key to unwrap THIS tenant's DEK into\nmemory. No auth token required (the master key IS the credential); never echoed\nor logged. Reachable even while sealed.","operationId":"vault_unseal_vault_unseal_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Vault Unseal Vault Unseal Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/status":{"get":{"summary":"Vault Status","description":"This tenant's vault posture — NEVER returns any secret value or key material.\nIntentionally unauthenticated (the unseal-recovery flow and liveness need it while sealed).\nNOTE: `secret_count`/`grant_count` are numeric counts only (no values); leaving them public is\na consciously-accepted LOW (see the 2026-09-15 audit) rather than break the documented status\nshape used by tooling/monitoring.","operationId":"vault_status_vault_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Vault Status Vault Status Get"}}}}}}},"/vault/env-secrets":{"get":{"summary":"Env Secret Sources","description":"Global admin: where each collector secret that used to live raw in the container env is\nserved from right now (WP-14, docs/secrets-in-vault.md) — `in_use` vault / env / missing, the\nDEFAULT tenant's vault name(s) with presence + version, whether the raw env var is still set\nand whether it equals the vault value (`env_removable`). NEVER a value. Reads the vault fresh\nand refreshes the in-process cache, so a just-written secret is in use after this call.","operationId":"env_secret_sources_vault_env_secrets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Env Secret Sources Vault Env Secrets Get"}}}}}}},"/vault/erasure-keyring/flagged-trials":{"get":{"summary":"Erasure Keyring Flagged Trials","description":"Global admin (S-48): trials granted while an unknown-kid trial fingerprint could not be checked\n(`trial_fingerprint_unverified`), each RE-CHECKED under the current keyring once the key is back.\nUser ids, kids and verdicts only. Nothing is revoked automatically.","operationId":"erasure_keyring_flagged_trials_vault_erasure_keyring_flagged_trials_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Erasure Keyring Flagged Trials Vault Erasure Keyring Flagged Trials Get"}}}}}}},"/vault/erasure-keyring":{"get":{"summary":"Erasure Keyring","description":"Global admin: per-kid record counts of the erasure keyring (S-48). Counts and key ids only.","operationId":"erasure_keyring_vault_erasure_keyring_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Erasure Keyring Vault Erasure Keyring Get"}}}}}}},"/secrets/{name}":{"post":{"summary":"Set Secret","description":"Admin, or a producer holding a write grant on `name`: encrypt `value` under the TENANT's\nDEK and emit secret.set. Optional `if_version` makes it a compare-and-swap (409\n`version_conflict`); it is REQUIRED for CAS_SECRETS (`router-routes`), whose value must also\npass the routing-table validation, incl. the fleet table's adapter-owner preservation (#62).","operationId":"set_secret_secrets__name__post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Secret Secrets  Name  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Secret","description":"Admin, or a producer holding a `delete` prefix grant covering `name` (#761): tombstone the\nsecret (emit secret.deleted). 404 if absent. `?if_version=` makes it a compare-and-swap;\nREQUIRED for CAS_SECRETS (which no prefix grant ever covers).","operationId":"delete_secret_secrets__name__delete","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"if_version","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"If Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Secret Secrets  Name  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Secret","description":"Resolve the bearer to its producer owner_id (in THIS tenant), require unseal +\na grant, then decrypt with the tenant's DEK and return {value}. Audited every call.","operationId":"get_secret_secrets__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Secret Secrets  Name  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/grants":{"get":{"summary":"List Grants","description":"Admin: list all grants for this tenant (producer_id + name + granted_at). NO values.\n`grants` are read grants (unchanged shape); `write_grants` the per-secret write grants.","operationId":"list_grants_vault_grants_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Grants Vault Grants Get"}}}}}},"post":{"summary":"Grant Secret","description":"Admin: grant a producer read access to a secret (emit secret.granted), or — with\n`access: \"write\"` — write access to exactly that secret (emit secret.write_granted).","operationId":"grant_secret_vault_grants_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Grant Secret Vault Grants Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/grants/prefix/{producer_id}/{prefix}":{"delete":{"summary":"Revoke Prefix Grant","description":"Admin: revoke one access level of a producer's prefix grant (#761) → secret.prefix_revoked.\nTakes effect on the next request (every check reads the projection; nothing is cached).","operationId":"revoke_prefix_grant_vault_grants_prefix__producer_id___prefix__delete","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}},{"name":"prefix","in":"path","required":true,"schema":{"type":"string","title":"Prefix"}},{"name":"access","in":"query","required":true,"schema":{"type":"string","title":"Access"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Prefix Grant Vault Grants Prefix  Producer Id   Prefix  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/grants/{producer_id}/{name}":{"delete":{"summary":"Revoke Secret","description":"Admin: revoke a producer's read grant (emit secret.revoked), or with `?access=write`\nits write grant (emit secret.write_revoked). The two are independent.","operationId":"revoke_secret_vault_grants__producer_id___name__delete","parameters":[{"name":"producer_id","in":"path","required":true,"schema":{"type":"string","title":"Producer Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"access","in":"query","required":false,"schema":{"type":"string","default":"read","title":"Access"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Secret Vault Grants  Producer Id   Name  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/vault/secrets":{"get":{"summary":"List Secrets","description":"Admin of THIS tenant (a tenant admin token, or a human owner/admin session at the tenant's\nhost): the names + versions of this tenant's secrets and whether the tenant's router producer\nis granted read on each. NEVER a value, NEVER another tenant's names — the listing is scoped\nto the Host-resolved tenant like every vault route, and the router's own open `/vault` names\nendpoint (a cross-tenant leak) is deliberately NOT mirrored. An uninitialised vault lists as\nempty (200); an initialised-but-sealed one is 503 like the other data routes.","operationId":"list_secrets_vault_secrets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Secrets Vault Secrets Get"}}}}}}},"/library/router-routes/{tenant}":{"get":{"summary":"Get Router Routes","description":"Redacted read-back of the tenant's stored routing table + grant status for the router\nproducer. 200 with `table: null` when nothing is stored (the UI's empty state).","operationId":"get_router_routes_library_router_routes__tenant__get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Router Routes","description":"Publish a table: validate (400 invalid_table with the same error shape), check\n`if_version` (409 version_conflict), then write the grants the router producer lacks and the\nsecret. `dry_run: true` stops before writing. `preserve_inline_keys: true` keeps the stored\ninline credential wherever the table carries the \"***\" placeholder.","operationId":"put_router_routes_library_router_routes__tenant__put","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/router-routes/{tenant}/validate":{"post":{"summary":"Validate Router Routes","description":"Validate a candidate table (object or JSON string) against the router's rules and this\ntenant's vault (names only). Never writes. `plan` says what a publish would do.","operationId":"validate_router_routes_library_router_routes__tenant__validate_post","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/router-status/{tenant}":{"get":{"summary":"Get Router Status","description":"Read-only router posture for a tenant admin: addon, producer, minted-token count, whether a\ntable is stored, the stated prerequisites and (when cheap) this month's usage ledger. Answers\n200 even when the tenant does not hold the router (`addon.held: false`) so the UI can say why\n— which, since the router is included with a paid workspace, means \"this workspace is not paid\nyet\" rather than \"buy the addon\".","operationId":"get_router_status_library_router_status__tenant__get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/library/router-traffic/{tenant}":{"get":{"summary":"Get Router Traffic","description":"What this tenant's routes actually carried — the month-to-date ledger plus, when the event\nindex can be read, the last 24 hours by the hour.\n\nSame auth as the status view (a logged-in owner/admin of the tenant, or a global admin for the\nfleet table); no router entitlement is needed, so a workspace that cannot use the router yet\ngets an honest empty answer rather than a hidden route. Always 200 on an authorised call:\n`available: false` with a `reason` is how \"the meter could not be read\" is said, because a\nzero here would read as a measurement.","operationId":"get_router_traffic_library_router_traffic__tenant__get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/credentials":{"get":{"summary":"List Credentials","operationId":"list_credentials_providers_credentials_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/credentials/{name}":{"get":{"summary":"Get Credential","operationId":"get_credential_providers_credentials__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Credential","description":"Set/clear non-secret metadata. 400 `value_not_allowed` when the body carries a value-shaped\nkey, `looks_like_secret` when a string looks like a credential. Tenant scope: only a name the\ntenant owns (in its vault or referenced by its own table).","operationId":"patch_credential_providers_credentials__name__patch","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/routes/{tenant}/lint":{"get":{"summary":"Lint Routes","description":"Lint the STORED table: dead-credential and orphan-session models, matrix-broken models,\nunreferenced models, agents whose every target is bad, and (fleet) a bad `sessions` list.\nSame auth as the table read-back; never a value (the table's inline keys never leave).","operationId":"lint_routes_providers_routes__tenant__lint_get","parameters":[{"name":"tenant","in":"path","required":true,"schema":{"type":"string","title":"Tenant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/matrix":{"get":{"summary":"Get Matrix","description":"The latest model-matrix verdict per (upstream route, upstream model): verdict, which of the\nfour cases passed, when. Router names, notes and error excerpts are never served.","operationId":"get_matrix_providers_matrix_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/usage":{"get":{"summary":"Get Usage","description":"The month view's usage read: one month of the router traffic ledger in every grouping\n(credential, agent, model, upstream and — fleet scope — tenant), the month's seal, and, for\nthe current month, the last 24 h by the hour. It is the one usage read the UI makes; the older\n`GET /library/router-traffic/{tenant}` and `GET /entities/usage_traffic` stay as aliases for\none release (same ledger, same numbers).\n\nScope and auth are the credential registry's (`_scope`): fleet scope sums every tenant's slice\nand adds `by_tenant`; tenant scope reads ONLY its own slice (the SQL `tenant=?` bind) and never\nsees a fleet credential name — foreign sessions read `platform` (owner decision 8). The reply\nkeeps the router-traffic top-level shape (`totals`, `by_agent/upstream/model`, `recent`,\n`window`, `measures`) so the routes join renders unchanged. Always 200 on an authorised call;\nan unreadable ledger is `available: false` with a `reason`, never a page of zeros.","operationId":"get_usage_providers_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/catalog":{"get":{"summary":"List Catalog","operationId":"list_catalog_providers_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/catalog/{entry_id}":{"get":{"summary":"Get Catalog Entry","operationId":"get_catalog_entry_providers_catalog__entry_id__get","parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/connections":{"get":{"summary":"List Connections","operationId":"list_connections_providers_connections_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Create Connection","operationId":"create_connection_providers_connections_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/connections/{conn_id}":{"get":{"summary":"Get Connection","description":"One connection, plus `table_usage`: where the published routing table uses it (the edit\nform's \"used by\" warning).","operationId":"get_connection_providers_connections__conn_id__get","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"string","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"summary":"Patch Connection","operationId":"patch_connection_providers_connections__conn_id__patch","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"string","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Connection","description":"Remove the connection record. Its key secret is left in the vault (delete it by name under\nVault if it is no longer needed). 409 while the stored routing table still uses it, unless\n`force=1` — the router keeps serving the last published expansion until a re-publish.","operationId":"delete_connection_providers_connections__conn_id__delete","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"string","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/connections/{conn_id}/key":{"post":{"summary":"Put Connection Key","description":"Write-only: store the connection's key in THIS tenant's vault under `key_secret`. The reply\ncarries the secret's name and new version, never the value.","operationId":"put_connection_key_providers_connections__conn_id__key_post","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"string","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/settings":{"get":{"summary":"Get Provider Settings","operationId":"get_provider_settings_providers_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"summary":"Put Provider Settings","description":"Turn the workspace's EU-only policy on/off. ON: new connections must be EU-resident, a\nrouting-table publish refuses a non-EU connection, and lint flags existing ones. It does not\ndelete anything.","operationId":"put_provider_settings_providers_settings_put","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/providers/connections/{conn_id}/test":{"post":{"summary":"Test Connection","operationId":"test_connection_providers_connections__conn_id__test_post","parameters":[{"name":"conn_id","in":"path","required":true,"schema":{"type":"string","title":"Conn Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/providers/probe-key":{"post":{"summary":"Redeem Probe Key","description":"The router's one read of a tenant key for ONE probe. Only a router producer\n(`AGENT_MDX_ROUTER_USAGE_PRODUCERS`) on the fleet-base host; the ticket is single-use and bound\nto (tenant, key_secret). Audited as `secret.accessed` in the tenant's vault stream.","operationId":"redeem_probe_key_providers_probe_key_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/webhook-adapters":{"get":{"summary":"List Webhook Adapters","operationId":"list_webhook_adapters_webhook_adapters_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Webhook Adapter","operationId":"register_webhook_adapter_webhook_adapters_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookAdapterRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/webhook-adapters/{adapter_id}/approve":{"post":{"summary":"Approve Webhook Adapter","operationId":"approve_webhook_adapter_webhook_adapters__adapter_id__approve_post","parameters":[{"name":"adapter_id","in":"path","required":true,"schema":{"type":"string","title":"Adapter Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/webhook-adapters/{adapter_id}":{"get":{"summary":"Get Webhook Adapter","operationId":"get_webhook_adapter_webhook_adapters__adapter_id__get","parameters":[{"name":"adapter_id","in":"path","required":true,"schema":{"type":"string","title":"Adapter Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Webhook Adapter","operationId":"delete_webhook_adapter_webhook_adapters__adapter_id__delete","parameters":[{"name":"adapter_id","in":"path","required":true,"schema":{"type":"string","title":"Adapter Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/webhooks/{adapter_id}":{"post":{"summary":"Webhook Ingress","operationId":"webhook_ingress_webhooks__adapter_id__post","parameters":[{"name":"adapter_id","in":"path","required":true,"schema":{"type":"string","title":"Adapter Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/normalizers":{"get":{"summary":"List Normalizers","operationId":"list_normalizers_normalizers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"summary":"Register Normalizer","operationId":"register_normalizer_normalizers_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NormalizerRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/normalizers/{normalizer_id}/approve":{"post":{"summary":"Approve Normalizer","operationId":"approve_normalizer_normalizers__normalizer_id__approve_post","parameters":[{"name":"normalizer_id","in":"path","required":true,"schema":{"type":"string","title":"Normalizer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/normalizers/{normalizer_id}":{"get":{"summary":"Get Normalizer","operationId":"get_normalizer_normalizers__normalizer_id__get","parameters":[{"name":"normalizer_id","in":"path","required":true,"schema":{"type":"string","title":"Normalizer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Normalizer","operationId":"delete_normalizer_normalizers__normalizer_id__delete","parameters":[{"name":"normalizer_id","in":"path","required":true,"schema":{"type":"string","title":"Normalizer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ArchiveEnvRequest":{"properties":{"purge":{"type":"boolean","title":"Purge","default":false},"dry_run":{"type":"boolean","title":"Dry Run","default":true}},"type":"object","title":"ArchiveEnvRequest"},"ArtifactValidateRequest":{"properties":{"kind":{"type":"string","maxLength":20,"minLength":1,"title":"Kind"},"target_path":{"type":"string","maxLength":400,"title":"Target Path","default":""},"content":{"type":"string","maxLength":200000,"title":"Content","default":""},"language":{"type":"string","maxLength":40,"title":"Language","default":""}},"type":"object","required":["kind"],"title":"ArtifactValidateRequest","description":"Phase 3 rung 4 gate — the meta-path guard + syntax check on a generated\nautomation artifact (a loop can never target its own grader)."},"AuthorizationDecisionRequest":{"properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"AuthorizationDecisionRequest"},"AuthorizationRequest":{"properties":{"candidate_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Id"},"artifact_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Artifact Ref"},"artifact_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Artifact Summary"},"score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Score"},"threshold":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Threshold"},"artifact":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Artifact"},"oracle_receipt":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Oracle Receipt"}},"type":"object","title":"AuthorizationRequest","description":"A request to put a process's shadow champion through the human-gated\nlive-authorization (environment-model + codegen authorize_live)."},"AuthzEnforcementRequest":{"properties":{"mode":{"type":"string","enum":["shadow","enforced"],"title":"Mode"}},"type":"object","required":["mode"],"title":"AuthzEnforcementRequest"},"DeleteConfirm":{"properties":{"confirm":{"type":"string","title":"Confirm","description":"must equal the archive label"}},"type":"object","required":["confirm"],"title":"DeleteConfirm"},"DesiredStateCandidateRequest":{"properties":{"manifest":{"additionalProperties":true,"type":"object","title":"Manifest"},"raw":{"anyOf":[{"type":"string","maxLength":200000},{"type":"null"}],"title":"Raw"},"note":{"type":"string","maxLength":2000,"title":"Note","default":""}},"type":"object","required":["manifest"],"title":"DesiredStateCandidateRequest","description":"A new fleet desired-state version (specs/fleet-desired-state/v0.1). The whole\n`FleetDesiredState` manifest is POSTed as a parsed dict (loose by design so the\nmanifest schema can evolve without a model migration — the promotion gate\nvalidates structure); `raw` is the optional original YAML text (for the git\nmirror/backup)."},"DiscoverRequest":{"properties":{"since_days":{"type":"integer","maximum":365.0,"minimum":1.0,"title":"Since Days","default":14},"max_events":{"type":"integer","maximum":100000.0,"minimum":1.0,"title":"Max Events","default":20000},"limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Limit","default":25}},"type":"object","title":"DiscoverRequest","description":"Phase 3 rung 1 — mine an env's own events into a friction-ranked automation\nbacklog. Read-only; window-bounded."},"EnvironmentCreateRequest":{"properties":{"id":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z][a-z0-9_-]*$","title":"Id"},"reads_from":{"items":{"type":"string"},"type":"array","title":"Reads From"},"description":{"type":"string","title":"Description","default":""},"min_objective_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Objective Tier"}},"type":"object","required":["id"],"title":"EnvironmentCreateRequest"},"EnvironmentEvalOracleRequest":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"hmac_key":{"type":"string","minLength":16,"title":"Hmac Key"},"require_receipt":{"type":"boolean","title":"Require Receipt","default":false}},"type":"object","required":["hmac_key"],"title":"EnvironmentEvalOracleRequest","description":"Register an environment's evaluation oracle for score verification\n(collector/receipts.py). `hmac_key` is the shared receipt-signing key —\nstored server-side only, NEVER returned by any read endpoint. With\n`require_receipt`, request_authorization REJECTS scores that don't carry a\nvalid receipt binding score == measured fitness; without it, verification\nis advisory (`score_verified` is recorded either way)."},"EnvironmentFrontierPolicyRequest":{"properties":{"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"frontier_policy":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Frontier Policy"}},"type":"object","title":"EnvironmentFrontierPolicyRequest","description":"Opt an environment in/out of frontier-coverage (spec frontier-coverage/v0.1).\n\n`kind` drives the expected-dimension prior; `frontier_policy` (a loose dict:\n``distinctness_theta``, ``require_probe_before_complete``,\n``external_integration_required``) turns the gate on. Only fields *present in\nthe request* are changed — omit one to leave it untouched, or send\n``frontier_policy: null`` to opt back out to legacy ``complete = all at_target``."},"EnvironmentGateEnforceRequest":{"properties":{"legs":{"items":{"type":"string"},"type":"array","title":"Legs"}},"type":"object","title":"EnvironmentGateEnforceRequest","description":"Per-environment STRICT at_target-gate opt-in (model-gate hardening). `legs`\nREPLACES this environment's enforced-leg set: a leg listed here makes that gate\nhard for THIS env even when the tenant-wide MODEL_GATE_ENFORCE does not list it\n(per-env can only ADD enforcement, never relax a tenant-wide gate). Empty list\nclears the env's own enforcement. Unknown legs are rejected."},"EnvironmentTrustRequest":{"properties":{"reads_from":{"items":{"type":"string"},"type":"array","title":"Reads From"}},"type":"object","title":"EnvironmentTrustRequest"},"FaithfulnessRequest":{"properties":{"score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Score"},"threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Threshold","default":0.0},"scope":{"type":"string","maxLength":120,"minLength":1,"title":"Scope","default":"_model"},"n_test":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"N Test"},"held_out":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Held Out"},"ground_truth_event_types":{"items":{"type":"string"},"type":"array","title":"Ground Truth Event Types"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["score"],"title":"FaithfulnessRequest","description":"A held-out model-faithfulness reading (environment-model v0.1 S4).\n`scope` is a process id, or '_model' for the env-wide model. `score` ∈ [0,1]\nis the held-out agreement with independent ground truth.\n\nNOTE (Phase 1, 1a): when a governed FaithfulnessSpec exists for (env, scope)\nthe collector RECOMPUTES the reading and IGNORES `score`/`threshold` here — they\nare retained only for the legacy (no-spec) path and are deprecated."},"FaithfulnessSpecRequest":{"properties":{"scope":{"type":"string","maxLength":120,"minLength":1,"title":"Scope","default":"_model"},"predicted":{"additionalProperties":true,"type":"object","title":"Predicted"},"ground_truth":{"additionalProperties":true,"type":"object","title":"Ground Truth"},"threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Threshold"},"test_frac":{"type":"number","exclusiveMaximum":1.0,"exclusiveMinimum":0.0,"title":"Test Frac","default":0.3},"compare":{"title":"Compare"}},"type":"object","required":["predicted","ground_truth","threshold"],"title":"FaithfulnessSpecRequest","description":"A GOVERNED faithfulness spec (Phase 1, 1a): declares HOW the collector\nrecomputes a scope's held-out faithfulness — the predicted field (from a schema\nentity type) vs. an INDEPENDENT ground-truth projection — plus the passing\nthreshold. Admin-only; the loop reads it, never authors it.\n  predicted:    {\"entity_type\": \"<schema entity>\", \"field\": \"<projected field>\"}\n  ground_truth: {\"event_types\": [...], \"key\": \"<dotted>\", \"value_path\": \"<dotted>\"}\n  compare:      \"exact\" | {\"numeric_tol\": <float>} (default exact)"},"FitnessRegisterRequest":{"properties":{"id":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Id"},"description":{"type":"string","title":"Description","default":""},"higher_is_better":{"type":"boolean","title":"Higher Is Better","default":true},"tier":{"type":"string","enum":["GROUND_TRUTH","EXTERNAL","DERIVED","SELF_REPORT"],"title":"Tier"},"select":{"type":"string","maxLength":2000,"minLength":1,"title":"Select"},"reduce":{"additionalProperties":true,"type":"object","title":"Reduce"},"scope":{"type":"string","enum":["process","environment"],"title":"Scope","default":"process"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"environment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Environment"}},"type":"object","required":["id","tier","select"],"title":"FitnessRegisterRequest"},"FleetSpecRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"pattern":"^[a-z][a-z0-9_.-]*$","title":"Name"},"kind":{"type":"string","enum":["container","pool","oauth_holder","router"],"title":"Kind","default":"container"},"host":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Host"},"image_digest":{"anyOf":[{"type":"string","pattern":"^sha256:[0-9a-f]{64}$"},{"type":"null"}],"title":"Image Digest"},"router":{"anyOf":[{"$ref":"#/components/schemas/RouterBlock"},{"type":"null"}]},"image":{"type":"string","maxLength":400,"minLength":1,"title":"Image"},"desired":{"type":"string","enum":["running","stopped"],"title":"Desired","default":"running"},"build":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Build"},"entrypoint":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Entrypoint"},"cmd":{"items":{"type":"string"},"type":"array","title":"Cmd"},"user":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"User"},"hostname":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Hostname"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"restart":{"type":"string","maxLength":50,"title":"Restart","default":"unless-stopped"},"env":{"additionalProperties":{"type":"string"},"type":"object","title":"Env"},"secret_refs":{"items":{"$ref":"#/components/schemas/SecretRef"},"type":"array","title":"Secret Refs"},"volumes":{"items":{"type":"string"},"type":"array","title":"Volumes"},"ports":{"items":{"type":"string"},"type":"array","title":"Ports"},"depends_on":{"items":{"type":"string"},"type":"array","title":"Depends On"},"replicas":{"anyOf":[{"type":"integer","maximum":20.0,"minimum":1.0},{"type":"null"}],"title":"Replicas"},"holder":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Holder"},"env_tokens":{"additionalProperties":{"type":"string"},"type":"object","title":"Env Tokens"},"description":{"type":"string","maxLength":2000,"title":"Description","default":""}},"type":"object","required":["name","image"],"title":"FleetSpecRequest","description":"A satellite service's declarative run-spec (specs/fleet-spec/v0.1; v0.2 adds\n`kind: \"router\"`, `host`, `image_digest` and the `router{}` block — all optional\nand omitted from the stored record when unset, so v0.1 records are unchanged).\nThe collector owns these so a removed fleet is rebuildable from the main\nservice; secrets are refs only (see SecretRef)."},"GlobalAdminTokenRequest":{"properties":{"label":{"type":"string","maxLength":200,"title":"Label","default":"global-admin (minted)"},"owner_id":{"type":"string","maxLength":200,"title":"Owner Id","default":""},"user_id":{"type":"string","maxLength":200,"title":"User Id","default":""}},"type":"object","title":"GlobalAdminTokenRequest","description":"Mint a global-admin token (specs/multi-tenancy/v0.1 Phase 2). Minted only by an\nexisting global admin (or break-glass)."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoopPromotion":{"properties":{"mode":{"type":"string","enum":["shadow","sandbox","live"],"title":"Mode","default":"shadow"}},"type":"object","title":"LoopPromotion"},"LoopRegisterRequest":{"properties":{"target":{"type":"string","maxLength":250,"minLength":1,"title":"Target"},"fitness":{"type":"string","maxLength":200,"title":"Fitness","default":""},"higher_is_better":{"type":"boolean","title":"Higher Is Better","default":true},"propose":{"type":"string","maxLength":250,"title":"Propose","default":"manual"},"station":{"type":"string","maxLength":100,"pattern":"^[a-z][a-z0-9_-]*$","title":"Station","default":"improvement-loop"},"subscriptions":{"items":{"$ref":"#/components/schemas/LoopSubscription"},"type":"array","title":"Subscriptions"},"promotion":{"$ref":"#/components/schemas/LoopPromotion"},"guardrails":{"additionalProperties":true,"type":"object","title":"Guardrails"}},"type":"object","required":["target"],"title":"LoopRegisterRequest"},"LoopSubscription":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"on":{"type":"string","maxLength":100,"minLength":1,"title":"On"},"where":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Where"},"cron":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cron"},"callback_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Callback Url"}},"type":"object","required":["name","on"],"title":"LoopSubscription"},"ModelSchemaRequest":{"properties":{"entities":{"items":{"additionalProperties":true,"type":"object"},"type":"array","minItems":1,"title":"Entities"},"relations":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Relations"},"description":{"type":"string","title":"Description","default":""}},"type":"object","required":["entities"],"title":"ModelSchemaRequest","description":"A domain ModelSchema for an environment (specs/environment-model/v0.1).\n`entities` is validated structurally in the route (each needs name+key+folds);\nkept loose here so the schema can evolve without a model migration."},"NormalizerRegisterRequest":{"properties":{"normalizer_id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9-]*$","title":"Normalizer Id"},"raw_event_types":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Raw Event Types"},"station":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z][a-z0-9_-]*$","title":"Station"},"resolvers":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Resolvers"},"rules":{"items":{"$ref":"#/components/schemas/WebhookRule"},"type":"array","minItems":1,"title":"Rules"},"first_match":{"type":"boolean","title":"First Match","default":false}},"type":"object","required":["normalizer_id","raw_event_types","station","rules"],"title":"NormalizerRegisterRequest"},"ProcessAdvanceRequest":{"properties":{"status":{"type":"string","title":"Status"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["status"],"title":"ProcessAdvanceRequest"},"ProcessRegisterRequest":{"properties":{"id":{"type":"string","maxLength":120,"minLength":1,"pattern":"^[a-z][a-z0-9_.:-]*$","title":"Id"},"loop_target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Loop Target"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"observed_by":{"items":{"type":"string"},"type":"array","title":"Observed By"},"automated_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Automated By"},"objective":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Objective"},"target":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target"},"depends_on":{"items":{"type":"string"},"type":"array","title":"Depends On"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"discovery":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Discovery"},"where":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Where"}},"type":"object","required":["id"],"title":"ProcessRegisterRequest","description":"A process node in an environment's process graph (environment-model v0.1\nS2). `loop_target` ties it to the satisficing loop whose loop.satisfied is the\ngoverned evidence for advancing to at_target."},"ProducerApproveRequest":{"properties":{"approved_stations":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Approved Stations"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"},"allowed_event_types":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":16,"minItems":1},{"type":"null"}],"title":"Allowed Event Types"}},"type":"object","required":["approved_stations"],"title":"ProducerApproveRequest"},"ProducerRegisterRequest":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"kind":{"type":"string","enum":["claude-skill","gh-action","webhook","dependabot","human","cron","impact-runner","ci-runner","collector"],"title":"Kind"},"requested_stations":{"items":{"type":"string"},"type":"array","title":"Requested Stations"},"contact":{"type":"string","maxLength":500,"minLength":1,"title":"Contact"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["name","kind","contact"],"title":"ProducerRegisterRequest"},"ProducerRejectRequest":{"properties":{"reason":{"type":"string","title":"Reason"}},"type":"object","required":["reason"],"title":"ProducerRejectRequest"},"ProducerRoleAssignRequest":{"properties":{"role":{"type":"string","maxLength":100,"minLength":1,"title":"Role"}},"type":"object","required":["role"],"title":"ProducerRoleAssignRequest"},"PromoteRequest":{"properties":{"version":{"type":"integer","minimum":1.0,"title":"Version"},"ack":{"type":"boolean","title":"Ack","default":false}},"type":"object","required":["version"],"title":"PromoteRequest","description":"Promote a candidate desired-state version to `active`. `version` must be the\ncurrent candidate. `ack` is a reserved extension point for a future dry-run-ack\ngate (unused in v0.1)."},"PruneEnvironmentsRequest":{"properties":{"environments":{"items":{"type":"string"},"type":"array","title":"Environments"},"confirm":{"type":"boolean","title":"Confirm","default":false}},"type":"object","required":["environments"],"title":"PruneEnvironmentsRequest"},"PruneRequest":{"properties":{"before":{"type":"string","title":"Before"},"event_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Event Types"},"dry_run":{"type":"boolean","title":"Dry Run","default":true}},"type":"object","required":["before"],"title":"PruneRequest"},"PurgeRequest":{"properties":{"event_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Event Types"},"stations":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Stations"},"before":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Before"},"dry_run":{"type":"boolean","title":"Dry Run","default":true}},"type":"object","title":"PurgeRequest"},"ReadTokenCreateRequest":{"properties":{"label":{"type":"string","title":"Label"},"scope":{"$ref":"#/components/schemas/ReadTokenScope"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["label"],"title":"ReadTokenCreateRequest"},"ReadTokenScope":{"properties":{"repositories":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Repositories"},"event_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Event Types"},"environments":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Environments"}},"type":"object","title":"ReadTokenScope"},"ReplayCorpus":{"properties":{"since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"},"until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Until"},"where":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Where"},"event_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Type"},"max_events":{"type":"integer","maximum":200000.0,"minimum":1.0,"title":"Max Events","default":50000}},"type":"object","title":"ReplayCorpus"},"ReplayRequest":{"properties":{"candidate":{"additionalProperties":true,"type":"object","title":"Candidate"},"fitness":{"type":"string","maxLength":200,"minLength":1,"title":"Fitness"},"target":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target"},"corpus":{"$ref":"#/components/schemas/ReplayCorpus"},"split":{"$ref":"#/components/schemas/ReplaySplit"}},"type":"object","required":["fitness"],"title":"ReplayRequest"},"ReplaySplit":{"properties":{"test_frac":{"type":"number","maximum":0.9,"minimum":0.0,"title":"Test Frac","default":0.3},"seed":{"type":"integer","title":"Seed","default":0}},"type":"object","title":"ReplaySplit"},"RepositoryRegisterRequest":{"properties":{"owner":{"type":"string","maxLength":200,"minLength":1,"title":"Owner"},"repo":{"type":"string","maxLength":200,"minLength":1,"title":"Repo"},"mainline_branch":{"type":"string","maxLength":250,"minLength":1,"title":"Mainline Branch"}},"type":"object","required":["owner","repo","mainline_branch"],"title":"RepositoryRegisterRequest"},"ResolveRequest":{"properties":{"capability":{"type":"string","maxLength":200,"minLength":1,"title":"Capability"},"provides":{"items":{"type":"string"},"type":"array","title":"Provides"}},"type":"object","required":["capability"],"title":"ResolveRequest","description":"Phase 3 rung 2.25 — resolve a missing capability to the best resolution\nstrategy (reuse > extend > build > loop_fetch; credential → escalate)."},"RollbackRequest":{"properties":{"version":{"type":"integer","minimum":1.0,"title":"Version"}},"type":"object","required":["version"],"title":"RollbackRequest","description":"Make a prior (already-gated) desired-state version `active` again."},"RouterBlock":{"properties":{"id":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$","title":"Id"},"role":{"type":"string","enum":["fleet","customer","internal","staging"],"title":"Role"},"env":{"type":"string","enum":["prod","staging"],"title":"Env","default":"prod"},"channel":{"type":"string","enum":["stable","canary"],"title":"Channel","default":"stable"},"pool":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Pool"},"region":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Region"},"producer":{"type":"string","maxLength":200,"minLength":1,"title":"Producer"},"status":{"type":"string","enum":["provisioning","active","draining","disabled","retired"],"title":"Status","default":"provisioning"},"weight":{"type":"integer","maximum":10000.0,"minimum":0.0,"title":"Weight","default":0},"edge":{"$ref":"#/components/schemas/RouterEdge"},"owner_operator":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Owner Operator"},"gate_profile":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Gate Profile"},"expected":{"$ref":"#/components/schemas/RouterExpected"},"expect":{"$ref":"#/components/schemas/RouterExpect"}},"additionalProperties":false,"type":"object","required":["id","role","producer"],"title":"RouterBlock","description":"fleet-spec v0.2 `router{}` block (router-fleet PLAN C1). Required iff\n`kind == \"router\"`; the cross-field rules (env allow-list, secret env_keys) live\nin `collector/router_registry.py`."},"RouterEdge":{"properties":{"unique_host":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Unique Host"},"aliases":{"items":{"type":"string"},"type":"array","maxItems":32,"title":"Aliases"},"meta":{"items":{"type":"string"},"type":"array","maxItems":32,"title":"Meta"},"public_ips":{"items":{"type":"string"},"type":"array","maxItems":32,"title":"Public Ips"},"type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Type"},"trusted_proxies":{"items":{"type":"string"},"type":"array","maxItems":32,"title":"Trusted Proxies"},"tls_mode":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Tls Mode"}},"additionalProperties":false,"type":"object","title":"RouterEdge","description":"fleet-spec v0.2 `router.edge` — how the router is reached (02 §P1)."},"RouterExpect":{"properties":{"env_names_sha256":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Env Names Sha256"},"config_fingerprint":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Config Fingerprint"},"build":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Build"}},"additionalProperties":false,"type":"object","title":"RouterExpect","description":"`router.expect` — fingerprints written by the deploy tool (03 §3.3 step 6)."},"RouterExpected":{"properties":{"posture":{"additionalProperties":true,"type":"object","title":"Posture"}},"additionalProperties":false,"type":"object","title":"RouterExpected","description":"`router.expected` — the posture the router MUST report (heartbeat drift input)."},"RouterHeartbeatRequest":{"properties":{"router_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Router Id"},"build":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Build"},"image_digest":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Image Digest"},"role":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Role"},"channel":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Channel"},"config_fingerprint":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Config Fingerprint"},"env_names_sha256":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Env Names Sha256"},"posture":{"additionalProperties":true,"type":"object","title":"Posture"},"capabilities":{"items":{"type":"string"},"type":"array","maxItems":64,"title":"Capabilities"},"counters":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"number"}]},"type":"object","title":"Counters"}},"type":"object","title":"RouterHeartbeatRequest","description":"`POST /fleet/routers/{id}/heartbeat` — observed state from the router itself\n(01 §3.4). Kept in memory only; never contains secret values."},"RouterStatusRequest":{"properties":{"status":{"type":"string","enum":["provisioning","active","draining","disabled","retired"],"title":"Status"},"reason":{"type":"string","maxLength":2000,"title":"Reason","default":""}},"type":"object","required":["status"],"title":"RouterStatusRequest","description":"`POST /fleet/routers/{id}/status` — lifecycle change."},"SecretRef":{"properties":{"env_key":{"type":"string","maxLength":100,"minLength":1,"title":"Env Key"},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"}},"type":"object","required":["env_key","name"],"title":"SecretRef","description":"A secret injected into a fleet resource BY NAME (specs/fleet-spec/v0.1).\nThe collector stores the ref only — the host-side executor resolves `name` to\nthe actual secret (e.g. /root/.polaris/<name>.txt) at run time. Never a value."},"StationDeactivateRequest":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"StationDeactivateRequest"},"StationRegisterRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z][a-z0-9_-]*$","title":"Name"},"description":{"type":"string","title":"Description","default":""},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"environment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Environment"}},"type":"object","required":["name"],"title":"StationRegisterRequest"},"SynthesizeRequest":{"properties":{"process":{"type":"string","maxLength":200,"minLength":1,"title":"Process"},"station":{"type":"string","maxLength":200,"title":"Station","default":""},"requires":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Requires"},"provides":{"items":{"type":"string"},"type":"array","title":"Provides"}},"type":"object","required":["process"],"title":"SynthesizeRequest","description":"Phase 3 rung 2 — the DETERMINISTIC gap analysis. `requires` is the proposer's\n(an LLM derives it client-side); the collector computes required − provided and\nreturns an automation or a dependency candidate."},"TenantAdminTokenRequest":{"properties":{"label":{"type":"string","maxLength":200,"title":"Label","default":"tenant-admin (minted)"},"owner_id":{"type":"string","maxLength":200,"title":"Owner Id","default":""}},"type":"object","title":"TenantAdminTokenRequest","description":"Mint a tenant-admin token for an existing tenant (global-admin only). The token\nis a pure tenant admin, scoped to that tenant."},"TenantCreateRequest":{"properties":{"id":{"type":"string","maxLength":63,"minLength":1,"pattern":"^[a-z][a-z0-9-]*$","title":"Id"},"hostnames":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Hostnames"},"display_name":{"type":"string","maxLength":200,"title":"Display Name","default":""},"seed_profile":{"type":"string","enum":["standard","minimal"],"title":"Seed Profile","default":"standard"},"ingress_ready":{"type":"boolean","title":"Ingress Ready","default":true},"quota":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Quota"},"description":{"type":"string","maxLength":2000,"title":"Description","default":""}},"type":"object","required":["id","hostnames"],"title":"TenantCreateRequest","description":"Create a tenant (specs/multi-tenancy/v0.1 Phase 2). Global-admin only.\nThe hostname's DNS/TLS/Ingress is provisioned off-system FIRST; this POST then\nregisters the mapping and seeds the tenant (a default env + a one-time\ntenant-admin token). `id` is also the data-subtree name."},"TenantPatchRequest":{"properties":{"hostnames":{"anyOf":[{"items":{"type":"string"},"type":"array","minItems":1},{"type":"null"}],"title":"Hostnames"},"status":{"anyOf":[{"type":"string","enum":["active","suspended"]},{"type":"null"}],"title":"Status"},"ingress_ready":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingress Ready"},"display_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Display Name"},"quota":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Quota"},"read_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Read Only"},"trial_expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trial Expires At"},"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan"}},"type":"object","title":"TenantPatchRequest","description":"Update a tenant: add/replace hostnames, suspend/resume, mark ingress ready,\nset quota. All fields optional; only provided ones are applied."},"TokenExpiryBackfillRequest":{"properties":{"apply":{"type":"boolean","title":"Apply","description":"false (default) = dry-run, no writes","default":false}},"type":"object","title":"TokenExpiryBackfillRequest"},"TokenMigrationApplyRequest":{"properties":{"legacy_kind":{"type":"string","title":"Legacy Kind","description":"'emit' or 'read'"},"legacy_id":{"type":"string","title":"Legacy Id","description":"emitter_token_id or read_token_id to replace"}},"type":"object","required":["legacy_kind","legacy_id"],"title":"TokenMigrationApplyRequest"},"TopicSensitivityRequest":{"properties":{"sensitivity":{"type":"string","enum":["open","restricted"],"title":"Sensitivity"}},"type":"object","required":["sensitivity"],"title":"TopicSensitivityRequest"},"UnifiedTokenCreateRequest":{"properties":{"base_role":{"type":"string","title":"Base Role","description":"'shim' (producer/emit) or 'reader' (read-only)"},"owner_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Id","description":"Required for base_role=shim: the APPROVED producer_id this token emits as. Ignored for reader (a self-id is generated)."},"label":{"type":"string","title":"Label","default":""},"grants":{"items":{"type":"string"},"type":"array","title":"Grants","description":"RESERVED per-token topic grants (Phase 4: stored but inert)."},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["base_role"],"title":"UnifiedTokenCreateRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookAdapterRegisterRequest":{"properties":{"adapter_id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9-]*$","title":"Adapter Id"},"mode":{"type":"string","enum":["direct","enrich"],"title":"Mode","default":"direct"},"station":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z][a-z0-9_-]*$","title":"Station"},"default_role":{"type":"string","enum":["author","validator","reviewer","approver","merger","observer","system"],"title":"Default Role","default":"system"},"auth":{"$ref":"#/components/schemas/WebhookAuth"},"rules":{"items":{"$ref":"#/components/schemas/WebhookRule"},"type":"array","minItems":1,"title":"Rules"},"first_match":{"type":"boolean","title":"First Match","default":false}},"type":"object","required":["adapter_id","station","auth","rules"],"title":"WebhookAdapterRegisterRequest"},"WebhookAuth":{"properties":{"type":{"type":"string","enum":["hmac","basic","bearer","none"],"title":"Type"},"header":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Header"},"algo":{"anyOf":[{"type":"string","enum":["sha256","sha1"]},{"type":"null"}],"title":"Algo"},"prefix":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Prefix"},"username":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Username"},"secret_name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Secret Name"}},"type":"object","required":["type"],"title":"WebhookAuth"},"WebhookRule":{"properties":{"id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9_-]*$","title":"Id"},"when":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"When"},"emit":{"additionalProperties":true,"type":"object","title":"Emit"}},"type":"object","required":["id"],"title":"WebhookRule"}}}}