@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2635 -86
- package/COMPARISON.md +80 -63
- package/CONTRIBUTING.md +84 -0
- package/MIGRATING-from-OpenSpec.md +213 -54
- package/QUICKSTART.md +125 -0
- package/README.md +450 -150
- package/ROADMAP.md +599 -0
- package/SCHEMA.md +2355 -256
- package/SECURITY.md +21 -3
- package/WORKFLOW.md +701 -0
- package/dist/cli.js +113 -19
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt/adopt.js +209 -0
- package/dist/commands/adopt/adopt.js.map +1 -0
- package/dist/commands/adopt/render.js +268 -0
- package/dist/commands/adopt/render.js.map +1 -0
- package/dist/commands/archive/archive.js +77 -0
- package/dist/commands/archive/archive.js.map +1 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
- package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
- package/dist/commands/archive/plan/contracts/openapi.js +159 -0
- package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
- package/dist/commands/archive/plan/gate.js +323 -0
- package/dist/commands/archive/plan/gate.js.map +1 -0
- package/dist/commands/archive/plan/landscape.js +180 -0
- package/dist/commands/archive/plan/landscape.js.map +1 -0
- package/dist/commands/archive/plan/refusal.js +111 -0
- package/dist/commands/archive/plan/refusal.js.map +1 -0
- package/dist/commands/archive/plan/specs.js +237 -0
- package/dist/commands/archive/plan/specs.js.map +1 -0
- package/dist/commands/archive/plan/state.js +27 -0
- package/dist/commands/archive/plan/state.js.map +1 -0
- package/dist/commands/archive/run.js +252 -0
- package/dist/commands/archive/run.js.map +1 -0
- package/dist/commands/context/context.js +99 -0
- package/dist/commands/context/context.js.map +1 -0
- package/dist/commands/context/print.js +283 -0
- package/dist/commands/context/print.js.map +1 -0
- package/dist/commands/delta/delta.js +279 -0
- package/dist/commands/delta/delta.js.map +1 -0
- package/dist/commands/delta/print.js +205 -0
- package/dist/commands/delta/print.js.map +1 -0
- package/dist/commands/dependencies.js +9 -7
- package/dist/commands/dependencies.js.map +1 -1
- package/dist/commands/diff/diff.js +93 -0
- package/dist/commands/diff/diff.js.map +1 -0
- package/dist/commands/diff/print.js +38 -0
- package/dist/commands/diff/print.js.map +1 -0
- package/dist/commands/doctor.js +5 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain/explain.js +151 -0
- package/dist/commands/explain/explain.js.map +1 -0
- package/dist/commands/explore.js +29 -24
- package/dist/commands/explore.js.map +1 -1
- package/dist/commands/gate/gate.js +115 -0
- package/dist/commands/gate/gate.js.map +1 -0
- package/dist/commands/gate/print.js +54 -0
- package/dist/commands/gate/print.js.map +1 -0
- package/dist/commands/gherkin/commit.js +146 -0
- package/dist/commands/gherkin/commit.js.map +1 -0
- package/dist/commands/gherkin/gherkin.js +246 -0
- package/dist/commands/gherkin/gherkin.js.map +1 -0
- package/dist/commands/gherkin/reconcile.js +149 -0
- package/dist/commands/gherkin/reconcile.js.map +1 -0
- package/dist/commands/gherkin/render.js +77 -0
- package/dist/commands/gherkin/render.js.map +1 -0
- package/dist/commands/init/example.js +204 -0
- package/dist/commands/init/example.js.map +1 -0
- package/dist/commands/init/first-hour.js +28 -0
- package/dist/commands/init/first-hour.js.map +1 -0
- package/dist/commands/{init.js → init/init.js} +146 -71
- package/dist/commands/init/init.js.map +1 -0
- package/dist/commands/init/mcp.js +131 -0
- package/dist/commands/init/mcp.js.map +1 -0
- package/dist/commands/init/options.js +78 -0
- package/dist/commands/init/options.js.map +1 -0
- package/dist/commands/instructions.js +72 -14
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/list/campaign/campaign.js +65 -0
- package/dist/commands/list/campaign/campaign.js.map +1 -0
- package/dist/commands/list/campaign/owners.js +65 -0
- package/dist/commands/list/campaign/owners.js.map +1 -0
- package/dist/commands/list/json.js +157 -0
- package/dist/commands/list/json.js.map +1 -0
- package/dist/commands/list/list.js +343 -0
- package/dist/commands/list/list.js.map +1 -0
- package/dist/commands/list/print.js +301 -0
- package/dist/commands/list/print.js.map +1 -0
- package/dist/commands/list/review.js +120 -0
- package/dist/commands/list/review.js.map +1 -0
- package/dist/commands/list/views.js +105 -0
- package/dist/commands/list/views.js.map +1 -0
- package/dist/commands/mcp/dispatch.js +183 -0
- package/dist/commands/mcp/dispatch.js.map +1 -0
- package/dist/commands/mcp/mcp.js +34 -0
- package/dist/commands/mcp/mcp.js.map +1 -0
- package/dist/commands/mcp/serve.js +55 -0
- package/dist/commands/mcp/serve.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/active.js +170 -0
- package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
- package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/living.js +62 -0
- package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
- package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
- package/dist/commands/migrate-openspec/materialize/target.js +219 -0
- package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
- package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
- package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/error.js +19 -0
- package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
- package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
- package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
- package/dist/commands/migrate-openspec/openspec/read.js +49 -0
- package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
- package/dist/commands/migrate-openspec/print.js +89 -0
- package/dist/commands/migrate-openspec/print.js.map +1 -0
- package/dist/commands/new/commit.js +76 -0
- package/dist/commands/new/commit.js.map +1 -0
- package/dist/commands/new/new.js +283 -0
- package/dist/commands/new/new.js.map +1 -0
- package/dist/commands/new/templates.js +355 -0
- package/dist/commands/new/templates.js.map +1 -0
- package/dist/commands/open.js +203 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/policy/format.js +152 -0
- package/dist/commands/policy/format.js.map +1 -0
- package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
- package/dist/commands/policy/gate.js.map +1 -0
- package/dist/commands/rebase/edit.js +106 -0
- package/dist/commands/rebase/edit.js.map +1 -0
- package/dist/commands/rebase/living.js +185 -0
- package/dist/commands/rebase/living.js.map +1 -0
- package/dist/commands/rebase/plan.js +245 -0
- package/dist/commands/rebase/plan.js.map +1 -0
- package/dist/commands/rebase/rebase.js +275 -0
- package/dist/commands/rebase/rebase.js.map +1 -0
- package/dist/commands/seed/commit.js +192 -0
- package/dist/commands/seed/commit.js.map +1 -0
- package/dist/commands/seed/plan.js +133 -0
- package/dist/commands/seed/plan.js.map +1 -0
- package/dist/commands/seed/seed.js +172 -0
- package/dist/commands/seed/seed.js.map +1 -0
- package/dist/commands/show/feature.js +178 -0
- package/dist/commands/show/feature.js.map +1 -0
- package/dist/commands/show/marks.js +24 -0
- package/dist/commands/show/marks.js.map +1 -0
- package/dist/commands/{show.js → show/service.js} +63 -152
- package/dist/commands/show/service.js.map +1 -0
- package/dist/commands/show/show.js +77 -0
- package/dist/commands/show/show.js.map +1 -0
- package/dist/commands/status/json.js +45 -0
- package/dist/commands/status/json.js.map +1 -0
- package/dist/commands/status/print.js +157 -0
- package/dist/commands/status/print.js.map +1 -0
- package/dist/commands/status/status.js +119 -0
- package/dist/commands/status/status.js.map +1 -0
- package/dist/commands/steps/steps.js +189 -0
- package/dist/commands/steps/steps.js.map +1 -0
- package/dist/commands/subsystem/edit.js +192 -0
- package/dist/commands/subsystem/edit.js.map +1 -0
- package/dist/commands/subsystem/move.js +265 -0
- package/dist/commands/subsystem/move.js.map +1 -0
- package/dist/commands/subsystem/query.js +115 -0
- package/dist/commands/subsystem/query.js.map +1 -0
- package/dist/commands/subsystem/subsystem.js +101 -0
- package/dist/commands/subsystem/subsystem.js.map +1 -0
- package/dist/commands/subsystem/sync.js +103 -0
- package/dist/commands/subsystem/sync.js.map +1 -0
- package/dist/commands/subsystem/txn/txn.js +94 -0
- package/dist/commands/subsystem/txn/txn.js.map +1 -0
- package/dist/commands/subsystem/txn/views.js +70 -0
- package/dist/commands/subsystem/txn/views.js.map +1 -0
- package/dist/commands/unarchive/manifest.js +160 -0
- package/dist/commands/unarchive/manifest.js.map +1 -0
- package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
- package/dist/commands/unarchive/restore.js.map +1 -0
- package/dist/commands/unarchive/unarchive.js +67 -0
- package/dist/commands/unarchive/unarchive.js.map +1 -0
- package/dist/commands/validate/arch-coverage.js +204 -0
- package/dist/commands/validate/arch-coverage.js.map +1 -0
- package/dist/commands/validate/checks/fleet-shape.js +296 -0
- package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
- package/dist/commands/validate/checks/health-deps.js +55 -0
- package/dist/commands/validate/checks/health-deps.js.map +1 -0
- package/dist/commands/validate/checks/requirements.js +254 -0
- package/dist/commands/validate/checks/requirements.js.map +1 -0
- package/dist/commands/validate/checks/sources.js +76 -0
- package/dist/commands/validate/checks/sources.js.map +1 -0
- package/dist/commands/validate/checks/vocabulary.js +31 -0
- package/dist/commands/validate/checks/vocabulary.js.map +1 -0
- package/dist/commands/validate/feature.js +216 -0
- package/dist/commands/validate/feature.js.map +1 -0
- package/dist/commands/validate/fleet/census.js +69 -0
- package/dist/commands/validate/fleet/census.js.map +1 -0
- package/dist/commands/validate/fleet/kind-tags.js +39 -0
- package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
- package/dist/commands/validate/fleet/landscape.js +353 -0
- package/dist/commands/validate/fleet/landscape.js.map +1 -0
- package/dist/commands/validate/fleet/load.js +52 -0
- package/dist/commands/validate/fleet/load.js.map +1 -0
- package/dist/commands/validate/fleet/obligations.js +270 -0
- package/dist/commands/validate/fleet/obligations.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
- package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
- package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/print.js +63 -0
- package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
- package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
- package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/place.js +13 -0
- package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
- package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/steps.js +197 -0
- package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
- package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
- package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
- package/dist/commands/validate/fleet/views/ids.js +40 -0
- package/dist/commands/validate/fleet/views/ids.js.map +1 -0
- package/dist/commands/validate/fleet/views/stale.js +59 -0
- package/dist/commands/validate/fleet/views/stale.js.map +1 -0
- package/dist/commands/validate/links/corpus.js +92 -0
- package/dist/commands/validate/links/corpus.js.map +1 -0
- package/dist/commands/validate/links/glossary.js +75 -0
- package/dist/commands/validate/links/glossary.js.map +1 -0
- package/dist/commands/validate/report.js +269 -0
- package/dist/commands/validate/report.js.map +1 -0
- package/dist/commands/validate/service/api.js +338 -0
- package/dist/commands/validate/service/api.js.map +1 -0
- package/dist/commands/validate/service/events/events.js +219 -0
- package/dist/commands/validate/service/events/events.js.map +1 -0
- package/dist/commands/validate/service/events/message-producers.js +77 -0
- package/dist/commands/validate/service/events/message-producers.js.map +1 -0
- package/dist/commands/validate/service/evidence-pins.js +131 -0
- package/dist/commands/validate/service/evidence-pins.js.map +1 -0
- package/dist/commands/validate/service/service.js +251 -0
- package/dist/commands/validate/service/service.js.map +1 -0
- package/dist/commands/validate/service/specs.js +251 -0
- package/dist/commands/validate/service/specs.js.map +1 -0
- package/dist/commands/validate/service/spine.js +113 -0
- package/dist/commands/validate/service/spine.js.map +1 -0
- package/dist/commands/validate/validate.js +338 -0
- package/dist/commands/validate/validate.js.map +1 -0
- package/dist/commands/verify/cross/diff.js +182 -0
- package/dist/commands/verify/cross/diff.js.map +1 -0
- package/dist/commands/verify/evidence/contract.js +32 -0
- package/dist/commands/verify/evidence/contract.js.map +1 -0
- package/dist/commands/verify/evidence/pins.js +52 -0
- package/dist/commands/verify/evidence/pins.js.map +1 -0
- package/dist/commands/verify/evidence/read.js +72 -0
- package/dist/commands/verify/evidence/read.js.map +1 -0
- package/dist/commands/verify/frozen.js +241 -0
- package/dist/commands/verify/frozen.js.map +1 -0
- package/dist/commands/verify/record.js +226 -0
- package/dist/commands/verify/record.js.map +1 -0
- package/dist/commands/verify/report.js +223 -0
- package/dist/commands/verify/report.js.map +1 -0
- package/dist/commands/verify/results.js +246 -0
- package/dist/commands/verify/results.js.map +1 -0
- package/dist/commands/verify/verify.js +217 -0
- package/dist/commands/verify/verify.js.map +1 -0
- package/dist/commands/vouch/contract.js +11 -0
- package/dist/commands/vouch/contract.js.map +1 -0
- package/dist/commands/vouch/pack/contract.js +2 -0
- package/dist/commands/vouch/pack/contract.js.map +1 -0
- package/dist/commands/vouch/pack/pack.js +266 -0
- package/dist/commands/vouch/pack/pack.js.map +1 -0
- package/dist/commands/vouch/pack/print.js +271 -0
- package/dist/commands/vouch/pack/print.js.map +1 -0
- package/dist/commands/vouch/pack/sections.js +142 -0
- package/dist/commands/vouch/pack/sections.js.map +1 -0
- package/dist/commands/vouch/prompt/confirm.js +46 -0
- package/dist/commands/vouch/prompt/confirm.js.map +1 -0
- package/dist/commands/vouch/report.js +101 -0
- package/dist/commands/vouch/report.js.map +1 -0
- package/dist/commands/vouch/run.js +285 -0
- package/dist/commands/vouch/run.js.map +1 -0
- package/dist/commands/vouch/sample/plan.js +125 -0
- package/dist/commands/vouch/sample/plan.js.map +1 -0
- package/dist/commands/vouch/sample/print.js +109 -0
- package/dist/commands/vouch/sample/print.js.map +1 -0
- package/dist/commands/vouch/vet/verify.js +123 -0
- package/dist/commands/vouch/vet/verify.js.map +1 -0
- package/dist/commands/vouch/vouch.js +176 -0
- package/dist/commands/vouch/vouch.js.map +1 -0
- package/dist/core/agent/agents-md/artifacts.js +220 -0
- package/dist/core/agent/agents-md/artifacts.js.map +1 -0
- package/dist/core/agent/agents-md/command-map.js +324 -0
- package/dist/core/agent/agents-md/command-map.js.map +1 -0
- package/dist/core/agent/agents-md/cycle.js +165 -0
- package/dist/core/agent/agents-md/cycle.js.map +1 -0
- package/dist/core/agent/agents-md/map/explain.js +34 -0
- package/dist/core/agent/agents-md/map/explain.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
- package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
- package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
- package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
- package/dist/core/agent/agents-md/map/mcp.js +41 -0
- package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
- package/dist/core/agent/agents-md/map/status.js +62 -0
- package/dist/core/agent/agents-md/map/status.js.map +1 -0
- package/dist/core/agent/agents-md/map/subsystem.js +32 -0
- package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
- package/dist/core/agent/agents-md/map/usecases.js +60 -0
- package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
- package/dist/core/agent/agents-md/refusals.js +246 -0
- package/dist/core/agent/agents-md/refusals.js.map +1 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
- package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
- package/dist/core/agent/agents-md/spine.js +40 -0
- package/dist/core/agent/agents-md/spine.js.map +1 -0
- package/dist/core/agent/agents-md.js +170 -0
- package/dist/core/agent/agents-md.js.map +1 -0
- package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
- package/dist/core/agent/agents-stamp.js.map +1 -0
- package/dist/core/agent/contract.js +2 -0
- package/dist/core/agent/contract.js.map +1 -0
- package/dist/core/agent/protocol.js +193 -0
- package/dist/core/agent/protocol.js.map +1 -0
- package/dist/core/agent/scaffold.js +259 -0
- package/dist/core/agent/scaffold.js.map +1 -0
- package/dist/core/agent/support/report.js +103 -0
- package/dist/core/agent/support/report.js.map +1 -0
- package/dist/core/agent/tools/dialects.js +150 -0
- package/dist/core/agent/tools/dialects.js.map +1 -0
- package/dist/core/agent/tools/registry.js +228 -0
- package/dist/core/agent/tools/registry.js.map +1 -0
- package/dist/core/agent/workflows/adopt.js +133 -0
- package/dist/core/agent/workflows/adopt.js.map +1 -0
- package/dist/core/agent/workflows/check.js +337 -0
- package/dist/core/agent/workflows/check.js.map +1 -0
- package/dist/core/agent/workflows/closing.js +262 -0
- package/dist/core/agent/workflows/closing.js.map +1 -0
- package/dist/core/agent/workflows/feature.js +105 -0
- package/dist/core/agent/workflows/feature.js.map +1 -0
- package/dist/core/agent/workflows/implement.js +105 -0
- package/dist/core/agent/workflows/implement.js.map +1 -0
- package/dist/core/agent/workflows/reference/authoring.js +209 -0
- package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
- package/dist/core/agent/workflows/reference/codes.js +65 -0
- package/dist/core/agent/workflows/reference/codes.js.map +1 -0
- package/dist/core/agent/workflows/reference/done-check.js +188 -0
- package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
- package/dist/core/agent/workflows/reference/reference.js +16 -0
- package/dist/core/agent/workflows/reference/reference.js.map +1 -0
- package/dist/core/agent/workflows/reference/spine.js +297 -0
- package/dist/core/agent/workflows/reference/spine.js.map +1 -0
- package/dist/core/asyncapi/baseline/plan.js +110 -0
- package/dist/core/asyncapi/baseline/plan.js.map +1 -0
- package/dist/core/asyncapi/baseline/surfaces.js +54 -0
- package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
- package/dist/core/asyncapi/depth.js +164 -0
- package/dist/core/asyncapi/depth.js.map +1 -0
- package/dist/core/asyncapi/digest.js +141 -0
- package/dist/core/asyncapi/digest.js.map +1 -0
- package/dist/core/asyncapi/merge/components.js +91 -0
- package/dist/core/asyncapi/merge/components.js.map +1 -0
- package/dist/core/asyncapi/merge/error.js +33 -0
- package/dist/core/asyncapi/merge/error.js.map +1 -0
- package/dist/core/asyncapi/merge/markers.js +308 -0
- package/dist/core/asyncapi/merge/markers.js.map +1 -0
- package/dist/core/asyncapi/merge/merge.js +215 -0
- package/dist/core/asyncapi/merge/merge.js.map +1 -0
- package/dist/core/asyncapi/merge/pin.js +107 -0
- package/dist/core/asyncapi/merge/pin.js.map +1 -0
- package/dist/core/asyncapi/model.js +11 -0
- package/dist/core/asyncapi/model.js.map +1 -0
- package/dist/core/asyncapi/producers.js +50 -0
- package/dist/core/asyncapi/producers.js.map +1 -0
- package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
- package/dist/core/asyncapi/read.js.map +1 -0
- package/dist/core/brief/brief.js +225 -0
- package/dist/core/brief/brief.js.map +1 -0
- package/dist/core/brief/checks.js +250 -0
- package/dist/core/brief/checks.js.map +1 -0
- package/dist/core/brief/landscape.js +194 -0
- package/dist/core/brief/landscape.js.map +1 -0
- package/dist/core/brief/targets.js +226 -0
- package/dist/core/brief/targets.js.map +1 -0
- package/dist/core/brief/unchecked.js +48 -0
- package/dist/core/brief/unchecked.js.map +1 -0
- package/dist/core/c4/arch.js +174 -0
- package/dist/core/c4/arch.js.map +1 -0
- package/dist/core/c4/likec4.js +90 -0
- package/dist/core/c4/likec4.js.map +1 -0
- package/dist/core/c4/parsed/deployment.js +158 -0
- package/dist/core/c4/parsed/deployment.js.map +1 -0
- package/dist/core/c4/parsed/dynamic-views.js +132 -0
- package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
- package/dist/core/c4/parsed/specification.js +78 -0
- package/dist/core/c4/parsed/specification.js.map +1 -0
- package/dist/core/c4/parsed/values.js +57 -0
- package/dist/core/c4/parsed/values.js.map +1 -0
- package/dist/core/c4/parsed/view-ids.js +75 -0
- package/dist/core/c4/parsed/view-ids.js.map +1 -0
- package/dist/core/c4/project/architecture.js +45 -0
- package/dist/core/c4/project/architecture.js.map +1 -0
- package/dist/core/c4/project/documents.js +58 -0
- package/dist/core/c4/project/documents.js.map +1 -0
- package/dist/core/c4/project/load.js +187 -0
- package/dist/core/c4/project/load.js.map +1 -0
- package/dist/core/c4/project/staged.js +220 -0
- package/dist/core/c4/project/staged.js.map +1 -0
- package/dist/core/c4/resolve/service.js +159 -0
- package/dist/core/c4/resolve/service.js.map +1 -0
- package/dist/core/c4/resolve/steps.js +144 -0
- package/dist/core/c4/resolve/steps.js.map +1 -0
- package/dist/core/c4/seed/fleet-file.js +201 -0
- package/dist/core/c4/seed/fleet-file.js.map +1 -0
- package/dist/core/c4/seed/items.js +91 -0
- package/dist/core/c4/seed/items.js.map +1 -0
- package/dist/core/c4/seed/stamp.js +48 -0
- package/dist/core/c4/seed/stamp.js.map +1 -0
- package/dist/core/c4/seed/template.js +109 -0
- package/dist/core/c4/seed/template.js.map +1 -0
- package/dist/core/c4/source-mask.js +82 -0
- package/dist/core/c4/source-mask.js.map +1 -0
- package/dist/core/c4/source-scan.js +227 -0
- package/dist/core/c4/source-scan.js.map +1 -0
- package/dist/core/c4/splice/authored-source.js +101 -0
- package/dist/core/c4/splice/authored-source.js.map +1 -0
- package/dist/core/c4/splice/contract.js +10 -0
- package/dist/core/c4/splice/contract.js.map +1 -0
- package/dist/core/c4/splice/delta-blocks.js +139 -0
- package/dist/core/c4/splice/delta-blocks.js.map +1 -0
- package/dist/core/c4/splice/identity/edges.js +36 -0
- package/dist/core/c4/splice/identity/edges.js.map +1 -0
- package/dist/core/c4/splice/landscape-merge.js +269 -0
- package/dist/core/c4/splice/landscape-merge.js.map +1 -0
- package/dist/core/c4/splice/placement.js +194 -0
- package/dist/core/c4/splice/placement.js.map +1 -0
- package/dist/core/c4/workspace.js +174 -0
- package/dist/core/c4/workspace.js.map +1 -0
- package/dist/core/capabilities/authoring/notes.js +141 -0
- package/dist/core/capabilities/authoring/notes.js.map +1 -0
- package/dist/core/capabilities/capabilities.js +124 -0
- package/dist/core/capabilities/capabilities.js.map +1 -0
- package/dist/core/capabilities/delta/doc.js +50 -0
- package/dist/core/capabilities/delta/doc.js.map +1 -0
- package/dist/core/capabilities/delta/overlay.js +129 -0
- package/dist/core/capabilities/delta/overlay.js.map +1 -0
- package/dist/core/capabilities/delta/summary.js +57 -0
- package/dist/core/capabilities/delta/summary.js.map +1 -0
- package/dist/core/capabilities/delta/tree.js +43 -0
- package/dist/core/capabilities/delta/tree.js.map +1 -0
- package/dist/core/capabilities/delta/uncovered.js +222 -0
- package/dist/core/capabilities/delta/uncovered.js.map +1 -0
- package/dist/core/capabilities/findings.js +342 -0
- package/dist/core/capabilities/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/findings.js +181 -0
- package/dist/core/capabilities/realizes/findings.js.map +1 -0
- package/dist/core/capabilities/realizes/join.js +143 -0
- package/dist/core/capabilities/realizes/join.js.map +1 -0
- package/dist/core/capabilities/rollup.js +199 -0
- package/dist/core/capabilities/rollup.js.map +1 -0
- package/dist/core/capabilities/tree.js +126 -0
- package/dist/core/capabilities/tree.js.map +1 -0
- package/dist/core/capabilities/usecase-join.js +277 -0
- package/dist/core/capabilities/usecase-join.js.map +1 -0
- package/dist/core/coherence/authoring/scaffold.js +177 -0
- package/dist/core/coherence/authoring/scaffold.js.map +1 -0
- package/dist/core/coherence/authoring/sentinels.js +74 -0
- package/dist/core/coherence/authoring/sentinels.js.map +1 -0
- package/dist/core/coherence/coherence.js +287 -0
- package/dist/core/coherence/coherence.js.map +1 -0
- package/dist/core/coherence/declared.js +269 -0
- package/dist/core/coherence/declared.js.map +1 -0
- package/dist/core/coherence/events/declared.js +206 -0
- package/dist/core/coherence/events/declared.js.map +1 -0
- package/dist/core/coherence/events/events.js +204 -0
- package/dist/core/coherence/events/events.js.map +1 -0
- package/dist/core/coherence/events/grades.js +166 -0
- package/dist/core/coherence/events/grades.js.map +1 -0
- package/dist/core/coherence/events/lookups.js +122 -0
- package/dist/core/coherence/events/lookups.js.map +1 -0
- package/dist/core/coherence/events/merged.js +40 -0
- package/dist/core/coherence/events/merged.js.map +1 -0
- package/dist/core/coherence/living.js +198 -0
- package/dist/core/coherence/living.js.map +1 -0
- package/dist/core/coherence/lookups.js +155 -0
- package/dist/core/coherence/lookups.js.map +1 -0
- package/dist/core/coherence/pending.js +39 -0
- package/dist/core/coherence/pending.js.map +1 -0
- package/dist/core/conflict-markers.js +60 -0
- package/dist/core/conflict-markers.js.map +1 -0
- package/dist/core/delta/claims.js +73 -0
- package/dist/core/delta/claims.js.map +1 -0
- package/dist/core/delta/delta.js +296 -0
- package/dist/core/delta/delta.js.map +1 -0
- package/dist/core/delta/document.js +177 -0
- package/dist/core/delta/document.js.map +1 -0
- package/dist/core/delta/scope.js +48 -0
- package/dist/core/delta/scope.js.map +1 -0
- package/dist/core/delta/select.js +237 -0
- package/dist/core/delta/select.js.map +1 -0
- package/dist/core/dependencies/dependencies.js +141 -0
- package/dist/core/dependencies/dependencies.js.map +1 -0
- package/dist/core/dependencies/facts.js +165 -0
- package/dist/core/dependencies/facts.js.map +1 -0
- package/dist/core/dependencies/fanin.js +88 -0
- package/dist/core/dependencies/fanin.js.map +1 -0
- package/dist/core/dependencies/graph.js +106 -0
- package/dist/core/dependencies/graph.js.map +1 -0
- package/dist/core/deployment/delta.js +188 -0
- package/dist/core/deployment/delta.js.map +1 -0
- package/dist/core/deployment/objects.js +145 -0
- package/dist/core/deployment/objects.js.map +1 -0
- package/dist/core/diff/base-git.js +148 -0
- package/dist/core/diff/base-git.js.map +1 -0
- package/dist/core/diff/base-state.js +209 -0
- package/dist/core/diff/base-state.js.map +1 -0
- package/dist/core/diff/current-state.js +96 -0
- package/dist/core/diff/current-state.js.map +1 -0
- package/dist/core/diff/scope/changed-paths.js +188 -0
- package/dist/core/diff/scope/changed-paths.js.map +1 -0
- package/dist/core/diff/semantic.js +243 -0
- package/dist/core/diff/semantic.js.map +1 -0
- package/dist/core/diff/victims.js +247 -0
- package/dist/core/diff/victims.js.map +1 -0
- package/dist/core/docs.js +7 -64
- package/dist/core/docs.js.map +1 -1
- package/dist/core/doctor/agents.js +222 -0
- package/dist/core/doctor/agents.js.map +1 -0
- package/dist/core/doctor/config.js +135 -0
- package/dist/core/doctor/config.js.map +1 -0
- package/dist/core/doctor/doctor.js +275 -0
- package/dist/core/doctor/doctor.js.map +1 -0
- package/dist/core/doctor/report.js +13 -0
- package/dist/core/doctor/report.js.map +1 -0
- package/dist/core/doctor/residue.js +110 -0
- package/dist/core/doctor/residue.js.map +1 -0
- package/dist/core/document/apply.js +77 -0
- package/dist/core/document/apply.js.map +1 -0
- package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
- package/dist/core/document/frontmatter.js.map +1 -0
- package/dist/core/document/grammar/directives.js +143 -0
- package/dist/core/document/grammar/directives.js.map +1 -0
- package/dist/core/document/parse.js +263 -0
- package/dist/core/document/parse.js.map +1 -0
- package/dist/core/document/scenarios.js +221 -0
- package/dist/core/document/scenarios.js.map +1 -0
- package/dist/core/document/spec.js +241 -0
- package/dist/core/document/spec.js.map +1 -0
- package/dist/core/{config.js → envelope/config.js} +79 -18
- package/dist/core/envelope/config.js.map +1 -0
- package/dist/core/envelope/json.js +175 -0
- package/dist/core/envelope/json.js.map +1 -0
- package/dist/core/{version.js → envelope/version.js} +3 -3
- package/dist/core/envelope/version.js.map +1 -0
- package/dist/core/explain/families.js +175 -0
- package/dist/core/explain/families.js.map +1 -0
- package/dist/core/explain/fix-tables.js +178 -0
- package/dist/core/explain/fix-tables.js.map +1 -0
- package/dist/core/explain/lookup.js +181 -0
- package/dist/core/explain/lookup.js.map +1 -0
- package/dist/core/explain/refusals.js +49 -0
- package/dist/core/explain/refusals.js.map +1 -0
- package/dist/core/explain/terms.js +144 -0
- package/dist/core/explain/terms.js.map +1 -0
- package/dist/core/explore/describe.js +105 -0
- package/dist/core/explore/describe.js.map +1 -0
- package/dist/core/{explore.js → explore/explore.js} +50 -101
- package/dist/core/explore/explore.js.map +1 -0
- package/dist/core/fleet-context.js +120 -78
- package/dist/core/fleet-context.js.map +1 -1
- package/dist/core/gate/checks.js +201 -0
- package/dist/core/gate/checks.js.map +1 -0
- package/dist/core/gate/partners.js +205 -0
- package/dist/core/gate/partners.js.map +1 -0
- package/dist/core/gate/report.js +47 -0
- package/dist/core/gate/report.js.map +1 -0
- package/dist/core/gate/verification.js +113 -0
- package/dist/core/gate/verification.js.map +1 -0
- package/dist/core/gherkin/digest.js +60 -0
- package/dist/core/gherkin/digest.js.map +1 -0
- package/dist/core/gherkin/emit.js +177 -0
- package/dist/core/gherkin/emit.js.map +1 -0
- package/dist/core/gherkin/read.js +76 -0
- package/dist/core/gherkin/read.js.map +1 -0
- package/dist/core/gherkin/stale.js +234 -0
- package/dist/core/gherkin/stale.js.map +1 -0
- package/dist/core/gherkin/stamp.js +77 -0
- package/dist/core/gherkin/stamp.js.map +1 -0
- package/dist/core/gherkin/steps/catalogue.js +154 -0
- package/dist/core/gherkin/steps/catalogue.js.map +1 -0
- package/dist/core/gherkin/steps/inventory.js +98 -0
- package/dist/core/gherkin/steps/inventory.js.map +1 -0
- package/dist/core/gherkin/steps/phrase.js +72 -0
- package/dist/core/gherkin/steps/phrase.js.map +1 -0
- package/dist/core/glossary/delta.js +106 -0
- package/dist/core/glossary/delta.js.map +1 -0
- package/dist/core/glossary/tree.js +86 -0
- package/dist/core/glossary/tree.js.map +1 -0
- package/dist/core/kernel/concurrency.js.map +1 -0
- package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
- package/dist/core/kernel/document-bytes.js.map +1 -0
- package/dist/core/kernel/fences.js +42 -0
- package/dist/core/kernel/fences.js.map +1 -0
- package/dist/core/kernel/ids/capability.js +72 -0
- package/dist/core/kernel/ids/capability.js.map +1 -0
- package/dist/core/kernel/ids/dirs.js +33 -0
- package/dist/core/kernel/ids/dirs.js.map +1 -0
- package/dist/core/kernel/ids/feature.js +75 -0
- package/dist/core/kernel/ids/feature.js.map +1 -0
- package/dist/core/kernel/ids/service.js +156 -0
- package/dist/core/kernel/ids/service.js.map +1 -0
- package/dist/core/kernel/ids/subsystem.js +63 -0
- package/dist/core/kernel/ids/subsystem.js.map +1 -0
- package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
- package/dist/core/kernel/path-safety.js.map +1 -0
- package/dist/core/kernel/records.js.map +1 -0
- package/dist/core/links/backlinks.js +68 -0
- package/dist/core/links/backlinks.js.map +1 -0
- package/dist/core/links/case.js +74 -0
- package/dist/core/links/case.js.map +1 -0
- package/dist/core/links/corpus.js +104 -0
- package/dist/core/links/corpus.js.map +1 -0
- package/dist/core/links/findings.js +110 -0
- package/dist/core/links/findings.js.map +1 -0
- package/dist/core/links/parse.js +236 -0
- package/dist/core/links/parse.js.map +1 -0
- package/dist/core/mcp/argv.js +111 -0
- package/dist/core/mcp/argv.js.map +1 -0
- package/dist/core/mcp/author-tools.js +72 -0
- package/dist/core/mcp/author-tools.js.map +1 -0
- package/dist/core/mcp/framing.js +46 -0
- package/dist/core/mcp/framing.js.map +1 -0
- package/dist/core/mcp/protocol.js +280 -0
- package/dist/core/mcp/protocol.js.map +1 -0
- package/dist/core/mcp/tools.js +314 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/obligations/obligations.js +106 -0
- package/dist/core/obligations/obligations.js.map +1 -0
- package/dist/core/openapi/baseline/gate.js +166 -0
- package/dist/core/openapi/baseline/gate.js.map +1 -0
- package/dist/core/openapi/baseline/plan.js +112 -0
- package/dist/core/openapi/baseline/plan.js.map +1 -0
- package/dist/core/openapi/baseline/record.js +175 -0
- package/dist/core/openapi/baseline/record.js.map +1 -0
- package/dist/core/openapi/depth.js +122 -0
- package/dist/core/openapi/depth.js.map +1 -0
- package/dist/core/openapi/digest.js +189 -0
- package/dist/core/openapi/digest.js.map +1 -0
- package/dist/core/{openapi.js → openapi/doc.js} +44 -106
- package/dist/core/openapi/doc.js.map +1 -0
- package/dist/core/openapi/merge/components.js +234 -0
- package/dist/core/openapi/merge/components.js.map +1 -0
- package/dist/core/openapi/merge/error.js +26 -0
- package/dist/core/openapi/merge/error.js.map +1 -0
- package/dist/core/openapi/merge/markers.js +208 -0
- package/dist/core/openapi/merge/markers.js.map +1 -0
- package/dist/core/openapi/merge/merge.js +256 -0
- package/dist/core/openapi/merge/merge.js.map +1 -0
- package/dist/core/openapi/merge/pin.js +128 -0
- package/dist/core/openapi/merge/pin.js.map +1 -0
- package/dist/core/openspec/decide/capabilities.js +244 -0
- package/dist/core/openspec/decide/capabilities.js.map +1 -0
- package/dist/core/openspec/decide/dispositions.js +63 -0
- package/dist/core/openspec/decide/dispositions.js.map +1 -0
- package/dist/core/openspec/decide/renames.js +179 -0
- package/dist/core/openspec/decide/renames.js.map +1 -0
- package/dist/core/openspec/decide/verdict.js +84 -0
- package/dist/core/openspec/decide/verdict.js.map +1 -0
- package/dist/core/openspec/inventory.js +221 -0
- package/dist/core/openspec/inventory.js.map +1 -0
- package/dist/core/openspec/model/mapping.js +76 -0
- package/dist/core/openspec/model/mapping.js.map +1 -0
- package/dist/core/openspec/model/model.js +65 -0
- package/dist/core/openspec/model/model.js.map +1 -0
- package/dist/core/openspec/scan/changes.js +235 -0
- package/dist/core/openspec/scan/changes.js.map +1 -0
- package/dist/core/openspec/scan/config.js +200 -0
- package/dist/core/openspec/scan/config.js.map +1 -0
- package/dist/core/openspec/scan/shape.js +260 -0
- package/dist/core/openspec/scan/shape.js.map +1 -0
- package/dist/core/openspec/scan/walk.js +133 -0
- package/dist/core/openspec/scan/walk.js.map +1 -0
- package/dist/core/openspec/scan/workspace.js +71 -0
- package/dist/core/openspec/scan/workspace.js.map +1 -0
- package/dist/core/owners/codeowners.js +141 -0
- package/dist/core/owners/codeowners.js.map +1 -0
- package/dist/core/pack/features.js +120 -0
- package/dist/core/pack/features.js.map +1 -0
- package/dist/core/pack/joins.js +112 -0
- package/dist/core/pack/joins.js.map +1 -0
- package/dist/core/pack/living.js +137 -0
- package/dist/core/pack/living.js.map +1 -0
- package/dist/core/pack/pack.js +76 -0
- package/dist/core/pack/pack.js.map +1 -0
- package/dist/core/permissions/permissions.js +87 -0
- package/dist/core/permissions/permissions.js.map +1 -0
- package/dist/core/projection/api.js +84 -0
- package/dist/core/projection/api.js.map +1 -0
- package/dist/core/projection/arch-slice.js +63 -0
- package/dist/core/projection/arch-slice.js.map +1 -0
- package/dist/core/projection/events.js +34 -0
- package/dist/core/projection/events.js.map +1 -0
- package/dist/core/provenance/findings.js +208 -0
- package/dist/core/provenance/findings.js.map +1 -0
- package/dist/core/provenance/git.js +225 -0
- package/dist/core/provenance/git.js.map +1 -0
- package/dist/core/provenance/gitq/moves.js +182 -0
- package/dist/core/provenance/gitq/moves.js.map +1 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
- package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
- package/dist/core/provenance/sample/scope.js +238 -0
- package/dist/core/provenance/sample/scope.js.map +1 -0
- package/dist/core/provenance/sample/sections.js +61 -0
- package/dist/core/provenance/sample/sections.js.map +1 -0
- package/dist/core/provenance/sources.js +263 -0
- package/dist/core/provenance/sources.js.map +1 -0
- package/dist/core/provenance/stamp.js +232 -0
- package/dist/core/provenance/stamp.js.map +1 -0
- package/dist/core/provenance/walk.js +157 -0
- package/dist/core/provenance/walk.js.map +1 -0
- package/dist/core/repo/authored/paths.js +210 -0
- package/dist/core/repo/authored/paths.js.map +1 -0
- package/dist/core/repo/entries.js +126 -0
- package/dist/core/repo/entries.js.map +1 -0
- package/dist/core/repo/paths.js +277 -0
- package/dist/core/repo/paths.js.map +1 -0
- package/dist/core/repo/repo.js +248 -0
- package/dist/core/repo/repo.js.map +1 -0
- package/dist/core/repo/service-target.js +153 -0
- package/dist/core/repo/service-target.js.map +1 -0
- package/dist/core/repo/state.js +58 -0
- package/dist/core/repo/state.js.map +1 -0
- package/dist/core/repo/tree/find.js +52 -0
- package/dist/core/repo/tree/find.js.map +1 -0
- package/dist/core/repo/tree/fs.js +64 -0
- package/dist/core/repo/tree/fs.js.map +1 -0
- package/dist/core/repo/tree/marker.js +61 -0
- package/dist/core/repo/tree/marker.js.map +1 -0
- package/dist/core/repo/tree/views.js +172 -0
- package/dist/core/repo/tree/views.js.map +1 -0
- package/dist/core/repo/tree/walk.js +234 -0
- package/dist/core/repo/tree/walk.js.map +1 -0
- package/dist/core/results.js +99 -2
- package/dist/core/results.js.map +1 -1
- package/dist/core/scaffold/landscape.js +131 -0
- package/dist/core/scaffold/landscape.js.map +1 -0
- package/dist/core/scaffold/readme.js +84 -0
- package/dist/core/scaffold/readme.js.map +1 -0
- package/dist/core/staging/commit.js +241 -0
- package/dist/core/staging/commit.js.map +1 -0
- package/dist/core/staging/interrupted.js +96 -0
- package/dist/core/staging/interrupted.js.map +1 -0
- package/dist/core/staging/lock.js +206 -0
- package/dist/core/staging/lock.js.map +1 -0
- package/dist/core/staging/recovery/finding.js +35 -0
- package/dist/core/staging/recovery/finding.js.map +1 -0
- package/dist/core/staging/recovery/intent.js +98 -0
- package/dist/core/staging/recovery/intent.js.map +1 -0
- package/dist/core/staging/recovery/recover.js +126 -0
- package/dist/core/staging/recovery/recover.js.map +1 -0
- package/dist/core/staging/recovery/residue.js +62 -0
- package/dist/core/staging/recovery/residue.js.map +1 -0
- package/dist/core/staging/snapshot.js +202 -0
- package/dist/core/staging/snapshot.js.map +1 -0
- package/dist/core/staging/txn/forward.js +171 -0
- package/dist/core/staging/txn/forward.js.map +1 -0
- package/dist/core/staging/txn/journal.js +139 -0
- package/dist/core/staging/txn/journal.js.map +1 -0
- package/dist/core/staging/txn/transaction.js +75 -0
- package/dist/core/staging/txn/transaction.js.map +1 -0
- package/dist/core/staging/writes.js +113 -0
- package/dist/core/staging/writes.js.map +1 -0
- package/dist/core/status/actions/execution.js +49 -0
- package/dist/core/status/actions/execution.js.map +1 -0
- package/dist/core/status/contracts.js +102 -0
- package/dist/core/status/contracts.js.map +1 -0
- package/dist/core/status/feature/artifacts.js +196 -0
- package/dist/core/status/feature/artifacts.js.map +1 -0
- package/dist/core/status/feature/feature.js +207 -0
- package/dist/core/status/feature/feature.js.map +1 -0
- package/dist/core/status/feature/next.js +150 -0
- package/dist/core/status/feature/next.js.map +1 -0
- package/dist/core/status/feature/state.js +21 -0
- package/dist/core/status/feature/state.js.map +1 -0
- package/dist/core/status/fleet/fleet.js +197 -0
- package/dist/core/status/fleet/fleet.js.map +1 -0
- package/dist/core/status/fleet/next.js +207 -0
- package/dist/core/status/fleet/next.js.map +1 -0
- package/dist/core/status/interrupted.js +97 -0
- package/dist/core/status/interrupted.js.map +1 -0
- package/dist/core/status/report.js +31 -0
- package/dist/core/status/report.js.map +1 -0
- package/dist/core/status/scan.js +41 -0
- package/dist/core/status/scan.js.map +1 -0
- package/dist/core/status/verification.js +201 -0
- package/dist/core/status/verification.js.map +1 -0
- package/dist/core/usecases/capability.js +169 -0
- package/dist/core/usecases/capability.js.map +1 -0
- package/dist/core/usecases/delta/claims.js +116 -0
- package/dist/core/usecases/delta/claims.js.map +1 -0
- package/dist/core/usecases/delta/flows.js +103 -0
- package/dist/core/usecases/delta/flows.js.map +1 -0
- package/dist/core/usecases/delta/overlay.js +72 -0
- package/dist/core/usecases/delta/overlay.js.map +1 -0
- package/dist/core/usecases/fleet.js +137 -0
- package/dist/core/usecases/fleet.js.map +1 -0
- package/dist/core/usecases/operations.js +111 -0
- package/dist/core/usecases/operations.js.map +1 -0
- package/dist/core/usecases/place.js +44 -0
- package/dist/core/usecases/place.js.map +1 -0
- package/dist/core/usecases/touch.js +101 -0
- package/dist/core/usecases/touch.js.map +1 -0
- package/dist/core/verify/answers.js +173 -0
- package/dist/core/verify/answers.js.map +1 -0
- package/dist/core/verify/build.js +150 -0
- package/dist/core/verify/build.js.map +1 -0
- package/dist/core/verify/checklist.js +201 -0
- package/dist/core/verify/checklist.js.map +1 -0
- package/dist/core/verify/claims/identity.js +61 -0
- package/dist/core/verify/claims/identity.js.map +1 -0
- package/dist/core/verify/cross/diff.js +97 -0
- package/dist/core/verify/cross/diff.js.map +1 -0
- package/dist/core/verify/evidence/contract.js +169 -0
- package/dist/core/verify/evidence/contract.js.map +1 -0
- package/dist/core/verify/file.js +257 -0
- package/dist/core/verify/file.js.map +1 -0
- package/dist/core/verify/pins/lint.js +157 -0
- package/dist/core/verify/pins/lint.js.map +1 -0
- package/dist/core/verify/pins/pin.js +95 -0
- package/dist/core/verify/pins/pin.js.map +1 -0
- package/dist/core/verify/record.js +142 -0
- package/dist/core/verify/record.js.map +1 -0
- package/dist/core/verify/store/commit.js +89 -0
- package/dist/core/verify/store/commit.js.map +1 -0
- package/dist/core/verify/store/render.js +57 -0
- package/dist/core/verify/store/render.js.map +1 -0
- package/dist/core/vocabulary/health.js +91 -0
- package/dist/core/vocabulary/health.js.map +1 -0
- package/dist/core/vocabulary/issue.js +58 -0
- package/dist/core/vocabulary/issue.js.map +1 -0
- package/dist/core/vocabulary/maturity.js +145 -0
- package/dist/core/vocabulary/maturity.js.map +1 -0
- package/dist/core/{report.js → vocabulary/report.js} +30 -2
- package/dist/core/vocabulary/report.js.map +1 -0
- package/dist/core/vocabulary/steps.js +266 -0
- package/dist/core/vocabulary/steps.js.map +1 -0
- package/dist/core/workspace/discover.js +239 -0
- package/dist/core/workspace/discover.js.map +1 -0
- package/dist/core/workspace/render.js +52 -0
- package/dist/core/workspace/render.js.map +1 -0
- package/examples/README.md +189 -0
- package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
- package/examples/docs/architecture/capabilities.yaml +31 -0
- package/examples/docs/architecture/landscape.likec4 +280 -0
- package/examples/docs/architecture/obligations.yaml +23 -0
- package/examples/docs/architecture/permissions.yaml +50 -0
- package/examples/docs/architecture/subsystems.likec4 +11 -0
- package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
- package/examples/docs/capabilities/checkout/spec.md +55 -0
- package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
- package/examples/docs/capabilities/order-notifications/spec.md +43 -0
- package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
- package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
- package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
- package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
- package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
- package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
- package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
- package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
- package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
- package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
- package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
- package/examples/docs/glossary/order.md +15 -0
- package/examples/docs/glossary/payments/authorization.md +14 -0
- package/examples/docs/likec4.config.json +9 -0
- package/examples/docs/loam.json +3 -0
- package/examples/docs/services/checkout-web/model.likec4 +109 -0
- package/examples/docs/services/checkout-web/spec.md +91 -0
- package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
- package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
- package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
- package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
- package/examples/docs/services/order-service/arch.spec.md +127 -0
- package/examples/docs/services/order-service/asyncapi.yaml +108 -0
- package/examples/docs/services/order-service/health.yaml +57 -0
- package/examples/docs/services/order-service/model.likec4 +138 -0
- package/examples/docs/services/order-service/openapi.yaml +257 -0
- package/examples/docs/services/order-service/runbook.md +62 -0
- package/examples/docs/services/order-service/spec.md +134 -0
- package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
- package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
- package/examples/docs/services/payment-service/arch.spec.md +73 -0
- package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
- package/examples/docs/services/payment-service/health.yaml +39 -0
- package/examples/docs/services/payment-service/model.likec4 +67 -0
- package/examples/docs/services/payment-service/openapi.yaml +151 -0
- package/examples/docs/services/payment-service/runbook.md +37 -0
- package/examples/docs/services/payment-service/spec.md +88 -0
- package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
- package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
- package/examples/docs/services/platform/identity-service/health.yaml +70 -0
- package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
- package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
- package/examples/docs/services/platform/identity-service/runbook.md +95 -0
- package/examples/docs/services/platform/identity-service/spec.md +119 -0
- package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
- package/examples/docs/services/platform/notification-service/health.yaml +35 -0
- package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
- package/examples/docs/services/platform/notification-service/runbook.md +48 -0
- package/examples/docs/services/platform/notification-service/spec.md +112 -0
- package/examples/docs/services/platform/subsystem.yaml +2 -0
- package/examples/fleet.yaml +57 -0
- package/package.json +19 -6
- package/dist/commands/adopt.js +0 -240
- package/dist/commands/adopt.js.map +0 -1
- package/dist/commands/archive.js +0 -1313
- package/dist/commands/archive.js.map +0 -1
- package/dist/commands/delta.js +0 -388
- package/dist/commands/delta.js.map +0 -1
- package/dist/commands/docs-repo-gate.js.map +0 -1
- package/dist/commands/format.js +0 -17
- package/dist/commands/format.js.map +0 -1
- package/dist/commands/gherkin.js +0 -309
- package/dist/commands/gherkin.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list.js +0 -295
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/migrate-openspec.js +0 -950
- package/dist/commands/migrate-openspec.js.map +0 -1
- package/dist/commands/new.js +0 -413
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/rebase.js +0 -356
- package/dist/commands/rebase.js.map +0 -1
- package/dist/commands/show.js.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/unarchive.js.map +0 -1
- package/dist/commands/validate.js +0 -1773
- package/dist/commands/validate.js.map +0 -1
- package/dist/commands/verify.js +0 -775
- package/dist/commands/verify.js.map +0 -1
- package/dist/commands/vouch.js +0 -421
- package/dist/commands/vouch.js.map +0 -1
- package/dist/core/agent.js +0 -2173
- package/dist/core/agent.js.map +0 -1
- package/dist/core/agents-stamp.js.map +0 -1
- package/dist/core/arch.js +0 -130
- package/dist/core/arch.js.map +0 -1
- package/dist/core/asyncapi.js.map +0 -1
- package/dist/core/brief.js +0 -755
- package/dist/core/brief.js.map +0 -1
- package/dist/core/coherence.js +0 -577
- package/dist/core/coherence.js.map +0 -1
- package/dist/core/concurrency.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/delta.js +0 -476
- package/dist/core/delta.js.map +0 -1
- package/dist/core/dependencies.js +0 -356
- package/dist/core/dependencies.js.map +0 -1
- package/dist/core/doctor.js +0 -596
- package/dist/core/doctor.js.map +0 -1
- package/dist/core/document-bytes.js.map +0 -1
- package/dist/core/explore.js.map +0 -1
- package/dist/core/frontmatter.js.map +0 -1
- package/dist/core/gherkin.js +0 -463
- package/dist/core/gherkin.js.map +0 -1
- package/dist/core/health.js +0 -67
- package/dist/core/health.js.map +0 -1
- package/dist/core/ids.js +0 -122
- package/dist/core/ids.js.map +0 -1
- package/dist/core/issue.js +0 -9
- package/dist/core/issue.js.map +0 -1
- package/dist/core/json.js +0 -74
- package/dist/core/json.js.map +0 -1
- package/dist/core/likec4.js +0 -489
- package/dist/core/likec4.js.map +0 -1
- package/dist/core/maturity.js +0 -66
- package/dist/core/maturity.js.map +0 -1
- package/dist/core/openapi-merge.js +0 -552
- package/dist/core/openapi-merge.js.map +0 -1
- package/dist/core/openapi.js.map +0 -1
- package/dist/core/openspec-inventory.js +0 -1440
- package/dist/core/openspec-inventory.js.map +0 -1
- package/dist/core/path-safety.js.map +0 -1
- package/dist/core/provenance.js +0 -787
- package/dist/core/provenance.js.map +0 -1
- package/dist/core/records.js.map +0 -1
- package/dist/core/repo.js +0 -438
- package/dist/core/repo.js.map +0 -1
- package/dist/core/report.js.map +0 -1
- package/dist/core/spec.js +0 -505
- package/dist/core/spec.js.map +0 -1
- package/dist/core/staging.js +0 -890
- package/dist/core/staging.js.map +0 -1
- package/dist/core/status.js +0 -1132
- package/dist/core/status.js.map +0 -1
- package/dist/core/steps.js +0 -72
- package/dist/core/steps.js.map +0 -1
- package/dist/core/verify.js +0 -807
- package/dist/core/verify.js.map +0 -1
- package/dist/core/version.js.map +0 -1
- /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
- /package/dist/core/{records.js → kernel/records.js} +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: payment-service
|
|
3
|
+
status: draft
|
|
4
|
+
owner: payments-team
|
|
5
|
+
sources:
|
|
6
|
+
- src/main/java/
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# payment-service
|
|
10
|
+
|
|
11
|
+
Owns payment authorization and capture. This is the **living spec** — the complete current
|
|
12
|
+
state. Feature deltas (ADDED/MODIFIED/REMOVED requirements) merge in here on `loam archive`;
|
|
13
|
+
`features/archive/` keeps every one of those deltas, so "which change introduced this
|
|
14
|
+
requirement" stays a search rather than a record somebody has to maintain.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
### Requirement: Authorize a payment
|
|
19
|
+
|
|
20
|
+
Requirement-ID: PAY-AUTHORIZE
|
|
21
|
+
The service SHALL reserve funds for an order before capture, and SHALL treat an authorization
|
|
22
|
+
request as idempotent by order id so that a caller's timeout-and-retry never reserves twice.
|
|
23
|
+
|
|
24
|
+
Operations: authorizePayment
|
|
25
|
+
Publishes: payment.PaymentAuthorized
|
|
26
|
+
Realizes: checkout#CHECKOUT-CHARGE-ONCE
|
|
27
|
+
|
|
28
|
+
#### Scenario: Successful authorization
|
|
29
|
+
- **Given** an order with a valid payment method
|
|
30
|
+
- **When** authorization is requested
|
|
31
|
+
- **Then** funds are reserved and a `PaymentAuthorized` event is emitted
|
|
32
|
+
|
|
33
|
+
#### Scenario: A retry of the same authorization returns the first result
|
|
34
|
+
- **Given** an authorization already reserved for order "A-1"
|
|
35
|
+
- **When** the same request arrives again after a caller timeout
|
|
36
|
+
- **Then** the original authorization is returned and no second reservation is made
|
|
37
|
+
|
|
38
|
+
#### Scenario: A second authorization for the same order with a different amount is refused
|
|
39
|
+
- **Given** an authorization already reserved for order "A-1" of 100.00 USD
|
|
40
|
+
- **When** an authorization of 120.00 USD is requested for the same order
|
|
41
|
+
- **Then** the request is refused with 409 and the first reservation stands
|
|
42
|
+
|
|
43
|
+
### Requirement: Capture an authorized payment
|
|
44
|
+
|
|
45
|
+
Requirement-ID: PAY-CAPTURE
|
|
46
|
+
The service SHALL settle a previously authorized payment, and SHALL refuse to capture a payment
|
|
47
|
+
it never authorized.
|
|
48
|
+
|
|
49
|
+
Operations: capturePayment
|
|
50
|
+
Publishes: payment.PaymentCaptured
|
|
51
|
+
Requires: service/payments:capture
|
|
52
|
+
|
|
53
|
+
#### Scenario: Capture an authorized payment
|
|
54
|
+
- **Given** an authorized payment
|
|
55
|
+
- **When** capture is requested
|
|
56
|
+
- **Then** the payment is settled and a `PaymentCaptured` event is emitted
|
|
57
|
+
|
|
58
|
+
#### Scenario: Capturing an unknown payment is refused
|
|
59
|
+
- **Given** a payment id no authorization ever created
|
|
60
|
+
- **When** capture is requested for it
|
|
61
|
+
- **Then** the request is refused with 404 and nothing is settled
|
|
62
|
+
|
|
63
|
+
### Requirement: Refund a captured payment
|
|
64
|
+
|
|
65
|
+
Requirement-ID: PAY-REFUND
|
|
66
|
+
The service SHALL return captured funds to the customer's payment method, SHALL reconcile the
|
|
67
|
+
refund against the acquirer before reporting it complete, and SHALL refuse a second refund of a
|
|
68
|
+
payment it has already refunded.
|
|
69
|
+
|
|
70
|
+
Operations: refundPayment
|
|
71
|
+
Publishes: payment.PaymentRefunded
|
|
72
|
+
Requires: user/payments:refund
|
|
73
|
+
|
|
74
|
+
#### Scenario: Refund a captured payment in full
|
|
75
|
+
- **Given** a captured payment of 100.00 USD
|
|
76
|
+
- **When** a refund is requested for it
|
|
77
|
+
- **Then** 100.00 USD is returned to the customer's payment method
|
|
78
|
+
- **And** the payment is recorded as refunded
|
|
79
|
+
|
|
80
|
+
#### Scenario: A second refund of the same payment is refused
|
|
81
|
+
- **Given** a payment already refunded in full
|
|
82
|
+
- **When** a refund is requested for it again
|
|
83
|
+
- **Then** the request is refused with 409 and no second refund is issued
|
|
84
|
+
|
|
85
|
+
#### Scenario: The refund is announced only after the acquirer reconciles
|
|
86
|
+
- **Given** a refund accepted by the acquirer but not yet reconciled
|
|
87
|
+
- **When** the reconciliation completes
|
|
88
|
+
- **Then** `payment.PaymentRefunded` is published exactly once for that payment
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-identity-service-0001
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-06-02
|
|
5
|
+
service: identity-service
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 1. Introspect tokens centrally instead of validating them locally
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
Every service in the fleet has to decide whether a caller's token is good. The
|
|
12
|
+
original answer was `GET /tokens/{token}/valid` (`validateToken`): a boolean, cheap
|
|
13
|
+
to call, and cheap to cache — which is precisely what made it wrong.
|
|
14
|
+
|
|
15
|
+
The endpoint answered from the token's signature and expiry, so it could only ever
|
|
16
|
+
say "this was issued by us and has not expired yet". It could not say "this client
|
|
17
|
+
was revoked eleven minutes ago". A revoked client therefore kept transacting until
|
|
18
|
+
its token's natural expiry, and lengthening token lifetimes — the obvious fix for the
|
|
19
|
+
load this endpoint put on the key store — made the revocation window longer in exact
|
|
20
|
+
proportion.
|
|
21
|
+
|
|
22
|
+
The boolean was also a dead end for authorization: a caller that needs the subject
|
|
23
|
+
and the scopes has to fetch them somewhere, and every consumer had begun decoding the
|
|
24
|
+
token itself to get them. Two services were already trusting claims they had not
|
|
25
|
+
verified.
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
`POST /tokens/introspect` (`introspectToken`) is the single answer, in the shape of
|
|
29
|
+
RFC 7662: it returns `active` computed from **revocation state**, together with the
|
|
30
|
+
subject and scopes, and an unknown, expired or revoked token is `{"active": false}`
|
|
31
|
+
with a 200 rather than a 4xx — the caller asked a question and got an answer.
|
|
32
|
+
|
|
33
|
+
`validateToken` is marked `deprecated: true` in `openapi.yaml` and keeps working. Its
|
|
34
|
+
verdict is now computed the same way as introspection's, so the two can never
|
|
35
|
+
disagree; only its response shape stays frozen.
|
|
36
|
+
|
|
37
|
+
Introspection is gated on `service/tokens:introspect` and served from a short-TTL
|
|
38
|
+
cache. Both obligations are written down where a test can be generated from them —
|
|
39
|
+
`IDN-INTROSPECT` in `spec.md` for the permission, `ARCH-INTROSPECT-CACHE` in
|
|
40
|
+
`arch.spec.md` for the cache's TTL, its invalidation on revocation, and its fallback.
|
|
41
|
+
|
|
42
|
+
## Consequences
|
|
43
|
+
- Revocation propagates within the cache TTL instead of within a token lifetime.
|
|
44
|
+
- Every consumer now makes a network call where it used to decode locally, which is
|
|
45
|
+
why the cache and its single-flight behaviour are architecture requirements rather
|
|
46
|
+
than an implementation detail; the stampede failure mode is in `runbook.md`.
|
|
47
|
+
- `validateToken` is deprecated rather than deleted, and that is a deliberate,
|
|
48
|
+
visible state rather than a decision postponed. payment-service still calls it —
|
|
49
|
+
the landscape edge `paymentService -> identityService` carries
|
|
50
|
+
`metadata { op 'validateToken' }` — so deleting the operation would break a
|
|
51
|
+
consumer with nothing having proposed the break. Instead the flag makes the
|
|
52
|
+
migration legible to `loam validate`: `spine.op-deprecated` names the consumer that
|
|
53
|
+
has not moved, and `api.requirement-deprecated` names `IDN-VALIDATE-LEGACY` as
|
|
54
|
+
behaviour on its way out. Both warnings stay until the migration is finished, and
|
|
55
|
+
they are how anyone can see it is not.
|
|
56
|
+
- Retirement is an explicit change, not a cleanup: a feature delta carries
|
|
57
|
+
`x-loam-remove: true` inside the operation in
|
|
58
|
+
`features/<FEAT>/specs/identity-service/openapi.yaml` plus a `REMOVED` requirement
|
|
59
|
+
naming `validateToken`, and `loam archive` deletes the operation and the
|
|
60
|
+
requirement together. That is the step that ends this ADR's transitional state.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: identity-service
|
|
3
|
+
status: draft
|
|
4
|
+
owner: platform-identity
|
|
5
|
+
sources:
|
|
6
|
+
- internal/tokens/
|
|
7
|
+
- cmd/
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# identity-service — architecture spec
|
|
11
|
+
|
|
12
|
+
The **living architecture spec**: the obligations no business scenario was ever going
|
|
13
|
+
to carry. Nothing in `spec.md` mentions key rotation or a cache TTL, because a caller
|
|
14
|
+
exchanging credentials for a token cannot observe either — and those are exactly the
|
|
15
|
+
places a coding agent cuts a corner unless the obligation is written where a test can
|
|
16
|
+
be generated from it.
|
|
17
|
+
|
|
18
|
+
Same grammar as `spec.md`, and one line more: `Covers:` is the architecture analog of
|
|
19
|
+
`Operations:`. Where a business requirement declares the operations it governs, an
|
|
20
|
+
architecture requirement declares the model objects its scenarios exercise — a C4
|
|
21
|
+
element id, an edge `source -> target`, or a health signal `sli:<id>` / `alert:<id>`.
|
|
22
|
+
`loam validate` grades the join in both directions: an entry that resolves to nothing
|
|
23
|
+
is `covers.unknown` (a mistyped id silently costs exactly the coverage it was written
|
|
24
|
+
for), and an SLI or alert in `health.yaml` that no requirement here covers is
|
|
25
|
+
`health.uncovered`. Every id below comes from `model.likec4` or `health.yaml` in this
|
|
26
|
+
directory; nothing here reaches for the landscape, because everything this service
|
|
27
|
+
touches is inside its own boundary.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
### Requirement: Signing keys rotate without invalidating live tokens
|
|
32
|
+
|
|
33
|
+
Requirement-ID: ARCH-KEY-ROTATION
|
|
34
|
+
The service SHALL keep the previous signing key verifiable for at least one full
|
|
35
|
+
token lifetime after promoting a new one, and SHALL never sign with a key that is
|
|
36
|
+
not already readable, from the key store, by every instance that answers
|
|
37
|
+
introspection. Rotation that flips both halves at once invalidates every token in
|
|
38
|
+
flight — an outage of the whole fleet, produced by a routine maintenance job, which
|
|
39
|
+
is why the overlap is a requirement and not a runbook note. The second half is the
|
|
40
|
+
one a single-instance test never catches: the signer and the verifier are different
|
|
41
|
+
processes reading the same store, and a key promoted before it lands there makes
|
|
42
|
+
one instance mint tokens the others report inactive.
|
|
43
|
+
|
|
44
|
+
Covers: identityService.keyStore, identityService.tokens -> identityService.keyStore
|
|
45
|
+
|
|
46
|
+
#### Scenario: A rotation keeps tokens minted a minute earlier verifiable
|
|
47
|
+
- **Given** the active key K1 and tokens issued under it with thirty minutes of life left
|
|
48
|
+
- **When** K2 is promoted to active
|
|
49
|
+
- **Then** new tokens are signed with K2
|
|
50
|
+
- **And** tokens signed with K1 keep verifying until the last of them has expired
|
|
51
|
+
|
|
52
|
+
#### Scenario: A key is readable by every instance before it signs anything
|
|
53
|
+
- **Given** a newly generated key that is not yet in the key store the other instances read
|
|
54
|
+
- **When** the rotation job runs
|
|
55
|
+
- **Then** the key is written to the key store first and only then promoted to active
|
|
56
|
+
- **And** no token is ever signed with a key another instance could not verify
|
|
57
|
+
|
|
58
|
+
#### Scenario: Rotation is refused while the key store is unreachable
|
|
59
|
+
- **Given** the key store is unavailable
|
|
60
|
+
- **When** the rotation job runs
|
|
61
|
+
- **Then** it fails without promoting anything and the previous active key stays in use
|
|
62
|
+
- **And** the fleet keeps issuing tokens rather than half-rotating
|
|
63
|
+
|
|
64
|
+
### Requirement: Introspection is cached, and the cache cannot outlive a revocation
|
|
65
|
+
|
|
66
|
+
Requirement-ID: ARCH-INTROSPECT-CACHE
|
|
67
|
+
The service SHALL answer introspection from a cache whose entries expire within the
|
|
68
|
+
revocation propagation budget, SHALL delete a token's entry when that token is
|
|
69
|
+
revoked, and SHALL fall back to the key store when the cache is unavailable. The
|
|
70
|
+
cache holds derived state only: losing it costs latency, never correctness, and any
|
|
71
|
+
design where a cache miss can produce a *different verdict* is the bug this
|
|
72
|
+
requirement exists to prevent.
|
|
73
|
+
|
|
74
|
+
Covers: identityService.introspectionCache, identityService.tokens -> identityService.introspectionCache
|
|
75
|
+
|
|
76
|
+
#### Scenario: A revocation invalidates the cached verdict immediately
|
|
77
|
+
- **Given** a token whose active verdict is cached
|
|
78
|
+
- **When** its client is revoked
|
|
79
|
+
- **Then** the cached entry is deleted as part of the revocation
|
|
80
|
+
- **And** the next introspection of that token reports inactive
|
|
81
|
+
|
|
82
|
+
#### Scenario: A cache entry cannot outlive the propagation budget
|
|
83
|
+
- **Given** a cached verdict written thirty seconds ago
|
|
84
|
+
- **When** it is read after its TTL has elapsed
|
|
85
|
+
- **Then** it is treated as a miss and the verdict is recomputed from revocation state
|
|
86
|
+
|
|
87
|
+
#### Scenario: The cache being down degrades latency, not the answer
|
|
88
|
+
- **Given** the introspection cache is unreachable
|
|
89
|
+
- **When** a token is introspected
|
|
90
|
+
- **Then** the verdict is computed from the revocations in the key store and is unchanged
|
|
91
|
+
- **And** the service stays available, paying for the miss in introspection latency alone
|
|
92
|
+
|
|
93
|
+
### Requirement: Token issuance is measured and paged
|
|
94
|
+
|
|
95
|
+
Requirement-ID: ARCH-ISSUE-HEALTH
|
|
96
|
+
The service SHALL export an availability and an issuance-latency SLI, and SHALL page
|
|
97
|
+
the identity on-call when issuance starts returning server errors. Issuance failing
|
|
98
|
+
is the one fault every other service in the fleet experiences as its own, so it is
|
|
99
|
+
paged rather than dashboarded.
|
|
100
|
+
|
|
101
|
+
Covers: sli:availability, sli:token_issue_latency_p99_ms, alert:token_issue_5xx
|
|
102
|
+
|
|
103
|
+
#### Scenario: Both SLIs are exported while the service serves traffic
|
|
104
|
+
- **Given** the service is serving token requests
|
|
105
|
+
- **When** its metrics endpoint is scraped
|
|
106
|
+
- **Then** `availability` and `token_issue_latency_p99_ms` report values against their SLOs
|
|
107
|
+
|
|
108
|
+
#### Scenario: Sustained issuance errors page the identity on-call
|
|
109
|
+
- **Given** more than 0.5% of token issuance requests return a server error over five minutes
|
|
110
|
+
- **When** the alert rules are evaluated
|
|
111
|
+
- **Then** `token_issue_5xx` pages the identity on-call
|
|
112
|
+
|
|
113
|
+
#### Scenario: An instance that cannot sign takes no traffic
|
|
114
|
+
- **Given** an instance whose active signing key failed to load
|
|
115
|
+
- **When** the readiness check is evaluated
|
|
116
|
+
- **Then** it reports not ready and is removed from the pool
|
|
117
|
+
- **And** the failure never reaches a caller as a server error
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Service health model: the signals this service promises to emit and the pages it
|
|
2
|
+
# promises to send. Targets and queries are authored here; the dependency graph
|
|
3
|
+
# comes from C4. Planned: `loam health` composes these across the fleet into a
|
|
4
|
+
# cascade / blast-radius view.
|
|
5
|
+
#
|
|
6
|
+
# `loam validate` reads exactly three things out of this file, all of them ids:
|
|
7
|
+
#
|
|
8
|
+
# * each `slis[].name` — every one wants a `Covers: sli:<id>` line in
|
|
9
|
+
# arch.spec.md, or `health.uncovered` says nothing tests the signal, and a
|
|
10
|
+
# signal nothing tests is dashboard decoration;
|
|
11
|
+
# * each `alerts[].name` — same obligation, through `Covers: alert:<id>`;
|
|
12
|
+
# * each `dependencies[]` id — which must resolve in this service's OWN
|
|
13
|
+
# model.likec4, or `health.dependency-unmodelled` fires.
|
|
14
|
+
#
|
|
15
|
+
# Queries, thresholds, pages and the checks below are authored prose that no check
|
|
16
|
+
# reads. They are here because the on-call engineer reads them.
|
|
17
|
+
service: identity-service
|
|
18
|
+
status: draft
|
|
19
|
+
|
|
20
|
+
slis:
|
|
21
|
+
- name: availability
|
|
22
|
+
# Every service that accepts a token calls this one, so this number is a
|
|
23
|
+
# ceiling on the fleet's: the 0.05% it permits is spent by every consumer at
|
|
24
|
+
# once. That is why it is set a notch tighter than payment-service's 0.999
|
|
25
|
+
# rather than matching it — a shared dependency cannot hold the same budget
|
|
26
|
+
# as the services depending on it and leave them any of their own.
|
|
27
|
+
query: "sum(rate(http_requests_total{job='identity-service',code!~'5..'}[5m])) / sum(rate(http_requests_total{job='identity-service'}[5m]))"
|
|
28
|
+
slo: 0.9995
|
|
29
|
+
- name: token_issue_latency_p99_ms
|
|
30
|
+
# Issuance alone, not introspection: minting signs with the active key and is
|
|
31
|
+
# the slow path, while introspection answers from cache. Averaging the two
|
|
32
|
+
# would let a signing stall hide behind cache hits.
|
|
33
|
+
query: "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{job='identity-service',path='/tokens'}[5m]))) * 1000"
|
|
34
|
+
slo: 150
|
|
35
|
+
|
|
36
|
+
alerts:
|
|
37
|
+
- name: token_issue_5xx
|
|
38
|
+
# Pages on issuance failing, which is the failure every other service feels as
|
|
39
|
+
# its own: a caller that cannot get a token cannot call anybody.
|
|
40
|
+
#
|
|
41
|
+
# A RATIO, not a raw error rate: ARCH-ISSUE-HEALTH promises a page at "more
|
|
42
|
+
# than 0.5% of token issuance requests", and `rate(5xx) > 0.005` would instead
|
|
43
|
+
# page at one error every 200 seconds — a threshold that means one thing at
|
|
44
|
+
# 10 rps and something else entirely at 1000. The five minutes the scenario
|
|
45
|
+
# names live in the range vector, so there is no second `for:` delay under it
|
|
46
|
+
# making the page later than the requirement says it comes.
|
|
47
|
+
expr: "sum(rate(http_requests_total{job='identity-service',path='/tokens',code=~'5..'}[5m])) / sum(rate(http_requests_total{job='identity-service',path='/tokens'}[5m])) > 0.005"
|
|
48
|
+
page: identity-oncall
|
|
49
|
+
|
|
50
|
+
checks:
|
|
51
|
+
liveness: GET /healthz
|
|
52
|
+
# Readiness fails while the active signing key cannot be loaded: an instance that
|
|
53
|
+
# is up and cannot sign should take no traffic, because it turns every issuance
|
|
54
|
+
# into a 5xx and burns the alert above instead of being rolled out of the pool.
|
|
55
|
+
readiness: GET /readyz
|
|
56
|
+
|
|
57
|
+
# There is deliberately NO `dependencies:` key here, and this comment is the
|
|
58
|
+
# difference between that fact and a forgotten section. identity-service is the
|
|
59
|
+
# fleet's root of trust: it calls no other service, publishes to no broker and
|
|
60
|
+
# reaches no third party, so it is named in other services' dependency lists
|
|
61
|
+
# (payment-service carries it as `degradable`) and names none of its own. Its two
|
|
62
|
+
# stores are inside its own boundary in model.likec4 (a private store nested in
|
|
63
|
+
# the service, never a fleet-level peer) and share its lifecycle rather than being
|
|
64
|
+
# something it depends on across a boundary.
|
|
65
|
+
#
|
|
66
|
+
# The day that stops being true, the new entry has to be drawn in
|
|
67
|
+
# services/identity-service/model.likec4 as well — resolution is against this
|
|
68
|
+
# service's own model and never the landscape, because the landscape carries only
|
|
69
|
+
# what crosses the service boundary while the model carries everything the service
|
|
70
|
+
# touches, and the model is the set an on-call file has to agree with.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// The identity-service C4 model: the containers behind the token API and the
|
|
2
|
+
// two stores they reach.
|
|
3
|
+
//
|
|
4
|
+
// The `specification` block is repeated in every .likec4 file on purpose. loam
|
|
5
|
+
// parses each document ALONE — it never stitches this file to
|
|
6
|
+
// architecture/landscape.likec4 before reading it — so a kind declared only in
|
|
7
|
+
// the landscape would resolve in the LikeC4 workspace and fail here, and the
|
|
8
|
+
// failure surfaces as `c4.invalid` on a file whose text looks perfect.
|
|
9
|
+
specification {
|
|
10
|
+
element softwareSystem
|
|
11
|
+
element container
|
|
12
|
+
element database
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
model {
|
|
16
|
+
identityService = softwareSystem 'identity-service' {
|
|
17
|
+
description 'Issues the access tokens the rest of the fleet presents, and answers whether one is still good'
|
|
18
|
+
// The binding — not the title — is what ties this element to
|
|
19
|
+
// services/identity-service/. With a title alone, renaming the box to
|
|
20
|
+
// 'Identity' would silently stop every join that reads this file (health
|
|
21
|
+
// dependencies, `Covers:` entries, the landscape spine) while `loam
|
|
22
|
+
// validate` stayed green, because a title that fails to match is only a
|
|
23
|
+
// guess at a binding and is graded as one.
|
|
24
|
+
metadata {
|
|
25
|
+
service 'identity-service'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
api = container 'api' {
|
|
29
|
+
description 'HTTP surface: POST /tokens, POST /tokens/introspect, GET /tokens/{token}/valid'
|
|
30
|
+
technology 'Go'
|
|
31
|
+
}
|
|
32
|
+
tokens = container 'tokens' {
|
|
33
|
+
description 'Mints and signs tokens, and turns a recorded revocation into an inactive verdict'
|
|
34
|
+
technology 'Go'
|
|
35
|
+
}
|
|
36
|
+
// Everything durable is in ONE store on purpose, and the description says
|
|
37
|
+
// which things, because two documents downstream depend on it: the cache
|
|
38
|
+
// requirement in arch.spec.md falls back HERE for a verdict, and the
|
|
39
|
+
// stampede in runbook.md is issuance and introspection contending for this
|
|
40
|
+
// store's connection pool. Naming only the signing keys here would leave
|
|
41
|
+
// both of them reaching for state nothing in this model holds.
|
|
42
|
+
keyStore = database 'key-store' {
|
|
43
|
+
description 'Signing keys and their rotation state, the client registry, and the revocations a verdict is computed from — the only durable state this service owns'
|
|
44
|
+
technology 'PostgreSQL'
|
|
45
|
+
}
|
|
46
|
+
// Derived state, so a plain container rather than a `database`: losing every
|
|
47
|
+
// byte in here costs latency and never correctness, and ARCH-INTROSPECT-CACHE
|
|
48
|
+
// in arch.spec.md is the requirement that says so in a scenario.
|
|
49
|
+
//
|
|
50
|
+
// Both stores stay NESTED inside the service boundary. Lifting either into
|
|
51
|
+
// architecture/landscape.likec4 as a peer is `landscape.datastore-private`:
|
|
52
|
+
// drawn at fleet level a store reads as a system in its own right, available
|
|
53
|
+
// for somebody else's service to depend on, which is the one coupling that is
|
|
54
|
+
// hardest to undo once a second team believes the picture.
|
|
55
|
+
introspectionCache = container 'introspection-cache' {
|
|
56
|
+
description 'Short-TTL introspection verdicts, keyed by token id'
|
|
57
|
+
technology 'Redis'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
api -> tokens 'Issues tokens, answers introspection and the legacy check'
|
|
61
|
+
// These three edges are the WHOLE runtime graph of this service:
|
|
62
|
+
// identity-service is the fleet's root of trust and calls nothing outside
|
|
63
|
+
// its own boundary, which is why health.yaml carries no `dependencies:`
|
|
64
|
+
// key. They still have to be drawn — with four nested elements and no edge
|
|
65
|
+
// joining any of them this model is `c4.no-relationships`, on the grounds
|
|
66
|
+
// that parts which reach nothing are almost never the truth. (The check is
|
|
67
|
+
// evidence-gated: one lone container proves nothing and stays silent, which
|
|
68
|
+
// is why the warning is about a model this shape and not about any model.)
|
|
69
|
+
tokens -> keyStore 'Signs with the active key; rotation promotes the next; introspection reads keys and revocations back'
|
|
70
|
+
tokens -> introspectionCache 'Caches introspection verdicts, invalidates on revocation'
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Views belong to LikeC4's renderer; no loam check reads anything below. One
|
|
75
|
+
// view is enough here because the whole model fits inside one boundary — the
|
|
76
|
+
// landscape splits its views only because a fleet-wide `include *` is the page
|
|
77
|
+
// nobody can read.
|
|
78
|
+
views {
|
|
79
|
+
view identity_service of identityService {
|
|
80
|
+
title 'identity-service — containers'
|
|
81
|
+
include *
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# The HTTP contract. `operationId` is the join token that ties this file to the
|
|
2
|
+
# other two axes: a landscape edge says `metadata { op 'introspectToken' }` and a
|
|
3
|
+
# requirement says `Operations: introspectToken`, and all three spellings must be
|
|
4
|
+
# byte-identical or the join is silently empty.
|
|
5
|
+
#
|
|
6
|
+
# loam reads operationIds from the eight HTTP methods of a path item and nowhere
|
|
7
|
+
# else — an id parked under a vendor extension (`x-legacy:`) does not exist as far
|
|
8
|
+
# as every check here is concerned, because a phantom id would mask a real
|
|
9
|
+
# contract break rather than document one.
|
|
10
|
+
openapi: 3.1.0
|
|
11
|
+
info:
|
|
12
|
+
title: identity-service
|
|
13
|
+
version: "2.0"
|
|
14
|
+
description: >-
|
|
15
|
+
Token issuance and introspection for the marketplace fleet. Every service that
|
|
16
|
+
accepts a caller's token resolves it here; nothing in this contract calls out.
|
|
17
|
+
|
|
18
|
+
paths:
|
|
19
|
+
/tokens:
|
|
20
|
+
post:
|
|
21
|
+
operationId: issueToken
|
|
22
|
+
summary: Exchange client credentials for a signed access token
|
|
23
|
+
requestBody:
|
|
24
|
+
required: true
|
|
25
|
+
content:
|
|
26
|
+
application/json:
|
|
27
|
+
schema:
|
|
28
|
+
$ref: '#/components/schemas/TokenRequest'
|
|
29
|
+
responses:
|
|
30
|
+
"201":
|
|
31
|
+
description: A signed token, valid until its stated expiry
|
|
32
|
+
# Every operation needs at least one response declaring
|
|
33
|
+
# `content: <media>: schema:` — without one, `openapi.response-undescribed`
|
|
34
|
+
# says the contract names the operation and nothing about what it
|
|
35
|
+
# returns, so a reader still has to open the code. 204 and 304 are the
|
|
36
|
+
# only codes excused, since neither carries a body.
|
|
37
|
+
content:
|
|
38
|
+
application/json:
|
|
39
|
+
schema:
|
|
40
|
+
$ref: '#/components/schemas/AccessToken'
|
|
41
|
+
"401":
|
|
42
|
+
description: The credentials did not authenticate
|
|
43
|
+
# A declared 4xx/5xx is a promise about a refusal, and loam grades it as
|
|
44
|
+
# one: this exact number must appear as a bare number inside the body of
|
|
45
|
+
# a scenario belonging to a requirement whose `Operations:` line names
|
|
46
|
+
# issueToken, or `api.response-ungoverned` fires. IDN-ISSUE's
|
|
47
|
+
# "unknown client" and "revoked secret" scenarios are where 401 is paid
|
|
48
|
+
# for — written as scenarios rather than prose, because a scenario is
|
|
49
|
+
# what `loam gherkin` turns into a test.
|
|
50
|
+
content:
|
|
51
|
+
application/json:
|
|
52
|
+
schema:
|
|
53
|
+
$ref: '#/components/schemas/AuthError'
|
|
54
|
+
|
|
55
|
+
/tokens/introspect:
|
|
56
|
+
post:
|
|
57
|
+
operationId: introspectToken
|
|
58
|
+
summary: Report whether a token is currently active and what it grants
|
|
59
|
+
description: >-
|
|
60
|
+
The authoritative answer, computed from revocation state — not from the
|
|
61
|
+
token's signature, which stays valid for the whole of a revoked token's
|
|
62
|
+
remaining lifetime.
|
|
63
|
+
requestBody:
|
|
64
|
+
required: true
|
|
65
|
+
content:
|
|
66
|
+
application/json:
|
|
67
|
+
schema:
|
|
68
|
+
$ref: '#/components/schemas/IntrospectionRequest'
|
|
69
|
+
responses:
|
|
70
|
+
# RFC 7662's shape, deliberately: an unknown, expired or revoked token is
|
|
71
|
+
# `{"active": false}` with a 200, never a 4xx. There is consequently no
|
|
72
|
+
# failure code to govern here, and `api.response-ungoverned` has nothing
|
|
73
|
+
# to say about this operation.
|
|
74
|
+
"200":
|
|
75
|
+
description: The verdict for the presented token
|
|
76
|
+
content:
|
|
77
|
+
application/json:
|
|
78
|
+
schema:
|
|
79
|
+
$ref: '#/components/schemas/Introspection'
|
|
80
|
+
|
|
81
|
+
/tokens/{token}/valid:
|
|
82
|
+
get:
|
|
83
|
+
operationId: validateToken
|
|
84
|
+
summary: Legacy boolean validity check
|
|
85
|
+
# `deprecated: true` is standard OpenAPI, and loam turns it into lifecycle
|
|
86
|
+
# visibility on the spine rather than leaving migration state to a wiki.
|
|
87
|
+
# Two findings come out of this one line, both warnings, both wanted here:
|
|
88
|
+
#
|
|
89
|
+
# * `spine.op-deprecated` — the landscape's
|
|
90
|
+
# `paymentService -> identityService` edge carries
|
|
91
|
+
# `metadata { op 'validateToken' }`, and payment-service has not moved
|
|
92
|
+
# yet. The finding is filed against the PROVIDER (this service, the
|
|
93
|
+
# edge's target) because the contract lives here, and it names the
|
|
94
|
+
# consumer that still has to migrate — one warning per inbound edge, so
|
|
95
|
+
# a deprecated operation nobody calls stays silent.
|
|
96
|
+
# * `api.requirement-deprecated` — IDN-VALIDATE-LEGACY governs only this
|
|
97
|
+
# operation, so the behaviour it describes is on its way out.
|
|
98
|
+
#
|
|
99
|
+
# Deprecation is the FIRST step of retiring an operation, never the removal
|
|
100
|
+
# itself: the op stays defined and callable, because deleting it here would
|
|
101
|
+
# break payment-service's edge with nothing having proposed the break. The
|
|
102
|
+
# step that ends this state is a feature delta, and its recipe is written
|
|
103
|
+
# once, in adrs/0001-token-introspection-over-local-validation.md.
|
|
104
|
+
deprecated: true
|
|
105
|
+
parameters:
|
|
106
|
+
- name: token
|
|
107
|
+
in: path
|
|
108
|
+
required: true
|
|
109
|
+
description: The opaque token id being checked
|
|
110
|
+
schema:
|
|
111
|
+
type: string
|
|
112
|
+
responses:
|
|
113
|
+
"200":
|
|
114
|
+
description: Whether the token is currently valid
|
|
115
|
+
content:
|
|
116
|
+
application/json:
|
|
117
|
+
schema:
|
|
118
|
+
$ref: '#/components/schemas/LegacyValidity'
|
|
119
|
+
|
|
120
|
+
components:
|
|
121
|
+
# Every schema this document references lives here, in the same file. An
|
|
122
|
+
# external `$ref` is out of scope on this axis — it does not travel with the
|
|
123
|
+
# contract when the contract is read on its own — and an internal one that
|
|
124
|
+
# points at nothing is `openapi.ref-unresolved`: the operation validates while
|
|
125
|
+
# its payload is silently absent, which reads exactly like a complete contract.
|
|
126
|
+
schemas:
|
|
127
|
+
TokenRequest:
|
|
128
|
+
type: object
|
|
129
|
+
required: [clientId, clientSecret]
|
|
130
|
+
properties:
|
|
131
|
+
clientId:
|
|
132
|
+
type: string
|
|
133
|
+
clientSecret:
|
|
134
|
+
type: string
|
|
135
|
+
format: password
|
|
136
|
+
scope:
|
|
137
|
+
type: string
|
|
138
|
+
description: Space-separated scopes; the issued token carries the intersection with what the client is granted
|
|
139
|
+
AccessToken:
|
|
140
|
+
type: object
|
|
141
|
+
required: [accessToken, tokenType, expiresIn]
|
|
142
|
+
properties:
|
|
143
|
+
accessToken:
|
|
144
|
+
type: string
|
|
145
|
+
tokenType:
|
|
146
|
+
type: string
|
|
147
|
+
const: Bearer
|
|
148
|
+
expiresIn:
|
|
149
|
+
type: integer
|
|
150
|
+
description: Seconds until expiry, counted from issuance
|
|
151
|
+
scope:
|
|
152
|
+
type: string
|
|
153
|
+
AuthError:
|
|
154
|
+
type: object
|
|
155
|
+
required: [error]
|
|
156
|
+
properties:
|
|
157
|
+
error:
|
|
158
|
+
type: string
|
|
159
|
+
# One value, on purpose: the refusal must not tell a caller whether the
|
|
160
|
+
# client id exists. IDN-ISSUE's two 401 scenarios are what hold that
|
|
161
|
+
# promise, and this enum is what makes breaking it a contract change.
|
|
162
|
+
enum: [invalid_client]
|
|
163
|
+
errorDescription:
|
|
164
|
+
type: string
|
|
165
|
+
description: Human-readable, never distinguishing an unknown client from a bad secret
|
|
166
|
+
IntrospectionRequest:
|
|
167
|
+
type: object
|
|
168
|
+
required: [token]
|
|
169
|
+
properties:
|
|
170
|
+
token:
|
|
171
|
+
type: string
|
|
172
|
+
Introspection:
|
|
173
|
+
type: object
|
|
174
|
+
required: [active]
|
|
175
|
+
properties:
|
|
176
|
+
active:
|
|
177
|
+
type: boolean
|
|
178
|
+
sub:
|
|
179
|
+
type: string
|
|
180
|
+
description: The client the token was issued to; absent when inactive
|
|
181
|
+
scope:
|
|
182
|
+
type: string
|
|
183
|
+
exp:
|
|
184
|
+
type: integer
|
|
185
|
+
description: Expiry as seconds since the epoch; absent when inactive
|
|
186
|
+
LegacyValidity:
|
|
187
|
+
type: object
|
|
188
|
+
required: [valid]
|
|
189
|
+
properties:
|
|
190
|
+
valid:
|
|
191
|
+
type: boolean
|
|
192
|
+
expiresAt:
|
|
193
|
+
type: string
|
|
194
|
+
format: date-time
|
|
195
|
+
description: >-
|
|
196
|
+
The only field this legacy shape carries beyond the boolean. Callers that
|
|
197
|
+
need scope or subject have to use introspectToken; this schema is frozen.
|