@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,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: order-service
|
|
3
|
+
status: draft
|
|
4
|
+
owner: orders-team
|
|
5
|
+
sources:
|
|
6
|
+
- src/main/kotlin/
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# order-service
|
|
10
|
+
|
|
11
|
+
Owns the order lifecycle — placement, the payment it orchestrates, and cancellation. This is
|
|
12
|
+
the **living spec**: the complete current state, not a changelog. Feature deltas
|
|
13
|
+
(`## ADDED|MODIFIED|REMOVED Requirements`) merge in here on `loam archive`, so what is written
|
|
14
|
+
below is always what the service promises today.
|
|
15
|
+
|
|
16
|
+
Three join lines carry the whole file into the rest of the docs, and each is graded:
|
|
17
|
+
`Operations:` names operationIds from `openapi.yaml` (an operation nobody names is
|
|
18
|
+
`api.ungoverned`; a name nothing defines is `spec-api.op-undefined`), `Publishes:` / `Consumes:`
|
|
19
|
+
name messages `asyncapi.yaml` declares an `action: send` / `action: receive` for
|
|
20
|
+
(`spec-event.message-undefined` otherwise), and `Requires:` names a pair
|
|
21
|
+
`architecture/permissions.yaml` declares (`permissions.unknown` otherwise). The architectural
|
|
22
|
+
obligations behind these promises — idempotency, the outbox, the dedupe ledger, the alerts —
|
|
23
|
+
are not here; they live in `arch.spec.md`, which is a separate requirement namespace.
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
### Requirement: Place an order
|
|
28
|
+
|
|
29
|
+
Requirement-ID: ORD-PLACE
|
|
30
|
+
The service SHALL accept an order for a customer's basket, obtain a payment authorization from
|
|
31
|
+
payment-service before acknowledging it, and announce the accepted order to the fleet. The
|
|
32
|
+
authorization answers in band — `authorizePayment` returns the reservation, so nothing is
|
|
33
|
+
acknowledged on a card nobody has reserved. The order is still placed in state
|
|
34
|
+
`awaiting_payment`: what clears that state is `payment.PaymentAuthorized`, and the requirement
|
|
35
|
+
that acts on it is ORD-ON-AUTHORIZED.
|
|
36
|
+
|
|
37
|
+
Operations: createOrder
|
|
38
|
+
Publishes: order.OrderPlaced
|
|
39
|
+
Realizes: checkout#CHECKOUT-CHARGE-ONCE
|
|
40
|
+
|
|
41
|
+
#### Scenario: A basket becomes an order
|
|
42
|
+
- **Given** a customer with a basket of two lines and a valid payment method
|
|
43
|
+
- **When** `createOrder` is called with a fresh `Idempotency-Key`
|
|
44
|
+
- **Then** the order is stored in state `awaiting_payment`
|
|
45
|
+
- **And** `order.OrderPlaced` is announced with the order id, the customer id and the total
|
|
46
|
+
|
|
47
|
+
#### Scenario: A reused idempotency key with a different basket is refused
|
|
48
|
+
- **Given** an order already placed under `Idempotency-Key` "ik-8842"
|
|
49
|
+
- **When** `createOrder` is called again with that key and a basket that differs from the first
|
|
50
|
+
- **Then** the service refuses with 409 and names the conflicting key
|
|
51
|
+
- **And** the first order is left exactly as it was placed
|
|
52
|
+
|
|
53
|
+
### Requirement: Read an order
|
|
54
|
+
|
|
55
|
+
Requirement-ID: ORD-READ
|
|
56
|
+
The service SHALL return an order's current state to its owner, so checkout-web's status page
|
|
57
|
+
reads the order rather than inferring it from payment events it cannot see.
|
|
58
|
+
|
|
59
|
+
Operations: getOrder
|
|
60
|
+
|
|
61
|
+
#### Scenario: An order is read back
|
|
62
|
+
- **Given** an order placed for customer "cus-31"
|
|
63
|
+
- **When** `getOrder` is called for that order id
|
|
64
|
+
- **Then** the response carries the order's state, its lines and its total
|
|
65
|
+
|
|
66
|
+
#### Scenario: An order id that was never issued
|
|
67
|
+
- **Given** an order id no placement ever produced
|
|
68
|
+
- **When** `getOrder` is called for it
|
|
69
|
+
- **Then** the service answers 404 rather than an empty order
|
|
70
|
+
|
|
71
|
+
### Requirement: Cancel an order
|
|
72
|
+
|
|
73
|
+
Requirement-ID: ORD-CANCEL
|
|
74
|
+
The service SHALL let an order be cancelled while nothing irreversible has happened to it, SHALL
|
|
75
|
+
return the customer's money when the order's payment was already captured, and SHALL refuse once
|
|
76
|
+
the order has been handed to fulfilment — a cancellation after that point is a return, which
|
|
77
|
+
this service does not model.
|
|
78
|
+
|
|
79
|
+
Operations: cancelOrder
|
|
80
|
+
Requires: user/orders:cancel
|
|
81
|
+
|
|
82
|
+
#### Scenario: A customer cancels before fulfilment
|
|
83
|
+
- **Given** an order in state `awaiting_payment`
|
|
84
|
+
- **When** its owner calls `cancelOrder`
|
|
85
|
+
- **Then** the order moves to `cancelled` and no further payment work is started
|
|
86
|
+
|
|
87
|
+
#### Scenario: Cancelling a confirmed order refunds its captured payment
|
|
88
|
+
- **Given** an order in state `confirmed` whose payment was captured
|
|
89
|
+
- **When** its owner calls `cancelOrder`
|
|
90
|
+
- **Then** `refundPayment` is called on payment-service for that payment
|
|
91
|
+
- **And** the order moves to `cancelled` only once the refund is recorded
|
|
92
|
+
|
|
93
|
+
#### Scenario: An order already handed to fulfilment cannot be cancelled
|
|
94
|
+
- **Given** an order in state `fulfilling`
|
|
95
|
+
- **When** `cancelOrder` is called for it
|
|
96
|
+
- **Then** the service refuses with 409 and the order stays `fulfilling`
|
|
97
|
+
|
|
98
|
+
### Requirement: Accept an order through the v1 API
|
|
99
|
+
|
|
100
|
+
Requirement-ID: ORD-PLACE-V1
|
|
101
|
+
The service SHALL keep accepting orders on the v1 endpoint for as long as the partner batch
|
|
102
|
+
importer still calls it. This is legacy: v1 takes a flat basket with no idempotency key and no
|
|
103
|
+
currency, so a retried import creates a second order and every total is assumed to be EUR. It
|
|
104
|
+
is kept alive for one remaining caller and nothing new may be built on it — FEAT-112 retires
|
|
105
|
+
the endpoint once that importer has moved to `createOrder`.
|
|
106
|
+
|
|
107
|
+
Operations: createOrderV1
|
|
108
|
+
|
|
109
|
+
#### Scenario: The partner batch importer places an order on v1
|
|
110
|
+
- **Given** the partner importer, the only caller left on v1
|
|
111
|
+
- **When** it posts a flat basket to `createOrderV1`
|
|
112
|
+
- **Then** an order is placed exactly as `createOrder` places one, with the currency defaulted to EUR
|
|
113
|
+
- **And** no idempotency key is recorded, so a replayed import would place a second order
|
|
114
|
+
|
|
115
|
+
### Requirement: Advance an order when payment is authorized
|
|
116
|
+
|
|
117
|
+
Requirement-ID: ORD-ON-AUTHORIZED
|
|
118
|
+
The service SHALL move an order to `confirmed` when payment-service announces that the order's
|
|
119
|
+
payment was authorized, and SHALL leave an order that is no longer awaiting payment untouched.
|
|
120
|
+
The authorization decision belongs to payment-service; what this requirement owns is the order
|
|
121
|
+
state that follows from it.
|
|
122
|
+
|
|
123
|
+
Consumes: payment.PaymentAuthorized
|
|
124
|
+
|
|
125
|
+
#### Scenario: Authorization confirms the order
|
|
126
|
+
- **Given** an order in state `awaiting_payment`
|
|
127
|
+
- **When** `payment.PaymentAuthorized` arrives naming that order
|
|
128
|
+
- **Then** the order moves to `confirmed` and becomes eligible for fulfilment
|
|
129
|
+
|
|
130
|
+
#### Scenario: Authorization arrives for an order the customer already cancelled
|
|
131
|
+
- **Given** an order cancelled while its authorization was still in flight
|
|
132
|
+
- **When** `payment.PaymentAuthorized` arrives naming that order
|
|
133
|
+
- **Then** the order stays `cancelled` and is never confirmed
|
|
134
|
+
- **And** the authorization is left to expire uncaptured, because this service never captures
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-payment-service-0001
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-05-10
|
|
5
|
+
service: payment-service
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 1. Use a transactional outbox for payment events
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
Payment state changes must publish events without dual-write races between the DB and Kafka.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
Persist events to an outbox table in the same transaction as the state change; a relay publishes to Kafka.
|
|
15
|
+
|
|
16
|
+
## Consequences
|
|
17
|
+
- At-least-once delivery with idempotent consumers.
|
|
18
|
+
- Extra outbox table and relay process to operate (see `runbook.md`).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ADR-payment-service-0002
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-06-18
|
|
5
|
+
service: payment-service
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 2. Make authorization idempotent by order id
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
Callers retry on timeout, and a timed-out authorization is an unknown outcome rather than a
|
|
12
|
+
failure: the funds may already be reserved at the acquirer. Retrying without an identity for the
|
|
13
|
+
request reserves twice, and the second reservation is invisible until a customer complains.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
`authorizePayment` is idempotent by order id. A repeat of a request already recorded returns the
|
|
17
|
+
original authorization; a request naming the same order with a *different* amount is refused
|
|
18
|
+
with `409` rather than treated as a new attempt, because the two cannot both be what the caller
|
|
19
|
+
meant. The same idempotency key travels to the acquirer, so the reconciliation job can replay a
|
|
20
|
+
timed-out call safely.
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
- Retries are safe, and `order-service` may retry `authorizePayment` without a compensating flow.
|
|
24
|
+
- The refusal path is a real branch of the contract, so it is written as a scenario rather than
|
|
25
|
+
as prose — `api.response-ungoverned` is what asks for it.
|
|
26
|
+
- An order whose amount legitimately changes needs a new order id, which the order lifecycle in
|
|
27
|
+
`services/order-service/` already gives it.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: payment-service
|
|
3
|
+
status: draft
|
|
4
|
+
owner: payments-team
|
|
5
|
+
sources:
|
|
6
|
+
- src/main/java/
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# payment-service — architecture spec
|
|
10
|
+
|
|
11
|
+
The **living architecture spec**: the obligations the business spec never carries —
|
|
12
|
+
the transactional outbox, retries, metrics and alerts. Same grammar as spec.md;
|
|
13
|
+
each requirement's `Covers:` line names the C4 elements, edges and health signals
|
|
14
|
+
its scenarios exercise, and `loam validate` checks every entry resolves
|
|
15
|
+
(`covers.unknown`) and every declared alert/SLI is covered (`health.uncovered`).
|
|
16
|
+
|
|
17
|
+
An edge entry resolves by exact element id **or** by the service an endpoint stands for, which
|
|
18
|
+
is why the entries below name `payment-service` rather than `marketplace.paymentService`: the
|
|
19
|
+
landscape draws this service inside a grouping element, and a `Covers:` line written against a
|
|
20
|
+
group path would have to be rewritten the day somebody moves the box.
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
### Requirement: Events leave through the transactional outbox
|
|
25
|
+
|
|
26
|
+
Requirement-ID: ARCH-PAY-OUTBOX
|
|
27
|
+
The service SHALL write a domain event and the state change it reports in one
|
|
28
|
+
database transaction, published to kafka by an outbox relay — never a dual write.
|
|
29
|
+
|
|
30
|
+
Covers: paymentService.outbox, payment-service -> kafka.paymentEvents
|
|
31
|
+
Publishes: payment.PaymentAuthorized, payment.PaymentCaptured
|
|
32
|
+
|
|
33
|
+
#### Scenario: Broker down at commit time
|
|
34
|
+
- **Given** an authorized payment whose `PaymentAuthorized` event is still in the outbox
|
|
35
|
+
- **When** kafka is unavailable
|
|
36
|
+
- **Then** the payment state stays committed and the event is published once kafka returns
|
|
37
|
+
|
|
38
|
+
#### Scenario: The relay redelivers rather than dropping
|
|
39
|
+
- **Given** an outbox row the relay published but could not mark as sent
|
|
40
|
+
- **When** the relay restarts
|
|
41
|
+
- **Then** the event is published a second time and consumers deduplicate on `paymentId`
|
|
42
|
+
|
|
43
|
+
### Requirement: Card authorization survives an acquirer timeout
|
|
44
|
+
|
|
45
|
+
Requirement-ID: ARCH-PAY-ACQUIRER
|
|
46
|
+
The service SHALL send an idempotency key with every acquirer call and SHALL reconcile a
|
|
47
|
+
timed-out authorization against the acquirer before deciding it failed — a timeout is an
|
|
48
|
+
unknown outcome, never a decline.
|
|
49
|
+
|
|
50
|
+
Covers: payment-service -> stripe
|
|
51
|
+
|
|
52
|
+
#### Scenario: The acquirer times out and the money was in fact reserved
|
|
53
|
+
- **Given** an authorization request that times out at the acquirer
|
|
54
|
+
- **When** the reconciliation job replays the request with the same idempotency key
|
|
55
|
+
- **Then** the acquirer returns the original authorization and no second charge exists
|
|
56
|
+
|
|
57
|
+
### Requirement: Authorization health is measured and paged
|
|
58
|
+
|
|
59
|
+
Requirement-ID: ARCH-PAY-HEALTH
|
|
60
|
+
The service SHALL export its availability and latency SLIs and page on a sustained
|
|
61
|
+
authorization error rate.
|
|
62
|
+
|
|
63
|
+
Covers: sli:availability, sli:latency_p99_ms, alert:payment_authorization_5xx
|
|
64
|
+
|
|
65
|
+
#### Scenario: Error-rate alert fires
|
|
66
|
+
- **Given** more than 1% of authorization requests fail over five minutes
|
|
67
|
+
- **When** the alert rules are evaluated
|
|
68
|
+
- **Then** `payment_authorization_5xx` pages the payments on-call
|
|
69
|
+
|
|
70
|
+
#### Scenario: SLIs are exported
|
|
71
|
+
- **Given** the service is serving traffic
|
|
72
|
+
- **When** its metrics endpoint is scraped
|
|
73
|
+
- **Then** `availability` and `latency_p99_ms` report values against their SLOs
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# The async contract — the messages this service puts on the bus.
|
|
2
|
+
#
|
|
3
|
+
# AsyncAPI 3.0 only. Its operations are named top-level objects carrying
|
|
4
|
+
# `action: send|receive`, which is what makes a message's direction legible;
|
|
5
|
+
# 2.x spells the same thing as publish/subscribe under a channel, where the
|
|
6
|
+
# two words are ambiguous about whose perspective they take.
|
|
7
|
+
#
|
|
8
|
+
# loam reads message NAMES and the `action` of the operation carrying them.
|
|
9
|
+
# It never joins on anything inside `payload` — the one look inside is a
|
|
10
|
+
# presence probe (a payload declaring no shape at all warns, a non-JSON
|
|
11
|
+
# `schemaFormat` is skipped) — which is what keeps swapping JSON Schema for
|
|
12
|
+
# Avro a `schemaFormat` line here rather than a change in loam.
|
|
13
|
+
#
|
|
14
|
+
# The name is the spine: the landscape edge's `metadata { publishes }`, the
|
|
15
|
+
# requirement's `Publishes:` line and `name` below are one name spelled three
|
|
16
|
+
# times, and they must be identical.
|
|
17
|
+
asyncapi: 3.0.0
|
|
18
|
+
info:
|
|
19
|
+
title: payment-service events
|
|
20
|
+
version: "1.0"
|
|
21
|
+
|
|
22
|
+
channels:
|
|
23
|
+
paymentEvents:
|
|
24
|
+
address: payment.events.v1
|
|
25
|
+
description: Payment lifecycle events, published by the outbox relay
|
|
26
|
+
messages:
|
|
27
|
+
PaymentAuthorized:
|
|
28
|
+
$ref: "#/components/messages/PaymentAuthorized"
|
|
29
|
+
PaymentCaptured:
|
|
30
|
+
$ref: "#/components/messages/PaymentCaptured"
|
|
31
|
+
PaymentRefunded:
|
|
32
|
+
$ref: "#/components/messages/PaymentRefunded"
|
|
33
|
+
|
|
34
|
+
operations:
|
|
35
|
+
sendPaymentAuthorized:
|
|
36
|
+
action: send
|
|
37
|
+
channel:
|
|
38
|
+
$ref: '#/channels/paymentEvents'
|
|
39
|
+
messages:
|
|
40
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentAuthorized'
|
|
41
|
+
sendPaymentCaptured:
|
|
42
|
+
action: send
|
|
43
|
+
channel:
|
|
44
|
+
$ref: '#/channels/paymentEvents'
|
|
45
|
+
messages:
|
|
46
|
+
- $ref: '#/channels/paymentEvents/messages/PaymentCaptured'
|
|
47
|
+
sendPaymentRefunded:
|
|
48
|
+
action: send
|
|
49
|
+
channel:
|
|
50
|
+
$ref: "#/channels/paymentEvents"
|
|
51
|
+
messages:
|
|
52
|
+
- $ref: "#/channels/paymentEvents/messages/PaymentRefunded"
|
|
53
|
+
|
|
54
|
+
components:
|
|
55
|
+
messages:
|
|
56
|
+
PaymentAuthorized:
|
|
57
|
+
# Namespaced by the domain that owns it. One message has exactly one
|
|
58
|
+
# producer: two services declaring they send this name is
|
|
59
|
+
# `asyncapi.message-contested`, and then which contract a consumer reads
|
|
60
|
+
# is a coin flip.
|
|
61
|
+
name: payment.PaymentAuthorized
|
|
62
|
+
title: Payment authorized
|
|
63
|
+
# JSON Schema today, because this fleet runs no schema registry. An Avro
|
|
64
|
+
# record here later needs a `schemaFormat:` line and no other change:
|
|
65
|
+
# everything below is opaque to loam.
|
|
66
|
+
payload:
|
|
67
|
+
type: object
|
|
68
|
+
required: [ paymentId, orderId, amount, currency, authorizedAt ]
|
|
69
|
+
properties:
|
|
70
|
+
paymentId:
|
|
71
|
+
type: string
|
|
72
|
+
format: uuid
|
|
73
|
+
orderId:
|
|
74
|
+
type: string
|
|
75
|
+
amount:
|
|
76
|
+
type: integer
|
|
77
|
+
description: minor units
|
|
78
|
+
currency:
|
|
79
|
+
type: string
|
|
80
|
+
pattern: '^[A-Z]{3}$'
|
|
81
|
+
authorizedAt:
|
|
82
|
+
type: string
|
|
83
|
+
format: date-time
|
|
84
|
+
PaymentCaptured:
|
|
85
|
+
name: payment.PaymentCaptured
|
|
86
|
+
title: Payment captured
|
|
87
|
+
payload:
|
|
88
|
+
type: object
|
|
89
|
+
required: [ paymentId, orderId, capturedAmount, currency, capturedAt ]
|
|
90
|
+
properties:
|
|
91
|
+
paymentId:
|
|
92
|
+
type: string
|
|
93
|
+
format: uuid
|
|
94
|
+
orderId:
|
|
95
|
+
type: string
|
|
96
|
+
capturedAmount:
|
|
97
|
+
type: integer
|
|
98
|
+
description: minor units
|
|
99
|
+
currency:
|
|
100
|
+
type: string
|
|
101
|
+
pattern: '^[A-Z]{3}$'
|
|
102
|
+
capturedAt:
|
|
103
|
+
type: string
|
|
104
|
+
format: date-time
|
|
105
|
+
PaymentRefunded:
|
|
106
|
+
name: payment.PaymentRefunded
|
|
107
|
+
title: Payment refunded
|
|
108
|
+
payload:
|
|
109
|
+
type: object
|
|
110
|
+
required:
|
|
111
|
+
- paymentId
|
|
112
|
+
- orderId
|
|
113
|
+
- refundedAmount
|
|
114
|
+
- currency
|
|
115
|
+
- refundedAt
|
|
116
|
+
properties:
|
|
117
|
+
paymentId:
|
|
118
|
+
type: string
|
|
119
|
+
format: uuid
|
|
120
|
+
orderId:
|
|
121
|
+
type: string
|
|
122
|
+
refundedAmount:
|
|
123
|
+
type: integer
|
|
124
|
+
description: minor units
|
|
125
|
+
currency:
|
|
126
|
+
type: string
|
|
127
|
+
pattern: ^[A-Z]{3}$
|
|
128
|
+
refundedAt:
|
|
129
|
+
type: string
|
|
130
|
+
format: date-time
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Service health model. Targets are authored; the dependency graph comes from
|
|
2
|
+
# C4 — this service's own model.likec4, which carries everything the service
|
|
3
|
+
# touches. planned: `loam health` composes these across the fleet -> cascade /
|
|
4
|
+
# blast-radius.
|
|
5
|
+
#
|
|
6
|
+
# `loam validate` reads only ids here: the `name` of each SLI and alert (every
|
|
7
|
+
# declared id wants a covering requirement in arch.spec.md, or
|
|
8
|
+
# `health.uncovered` says nothing tests it), and each dependency's `service:`
|
|
9
|
+
# id, which must resolve in model.likec4 (`health.dependency-unmodelled`
|
|
10
|
+
# otherwise). A dependency a feature in flight introduces arrives with that
|
|
11
|
+
# feature — it is not a dependency of the living service yet, which is why
|
|
12
|
+
# payment-split-service is absent from the list below while FEAT-101 is open.
|
|
13
|
+
#
|
|
14
|
+
# Everything else — the queries, the thresholds, the criticality words — is
|
|
15
|
+
# authored prose no check reads. That is deliberate: loam grades whether the
|
|
16
|
+
# signal is tested, never whether the threshold is right.
|
|
17
|
+
service: payment-service
|
|
18
|
+
status: draft
|
|
19
|
+
slis:
|
|
20
|
+
- name: availability
|
|
21
|
+
query: "sum(rate(http_requests_total{code!~'5..'}[5m])) / sum(rate(http_requests_total[5m]))"
|
|
22
|
+
slo: 0.999
|
|
23
|
+
- name: latency_p99_ms
|
|
24
|
+
query: "histogram_quantile(0.99, http_request_duration_seconds_bucket)"
|
|
25
|
+
slo: 300
|
|
26
|
+
alerts:
|
|
27
|
+
- name: payment_authorization_5xx
|
|
28
|
+
expr: "rate(http_requests_total{path='/payments',code=~'5..'}[5m]) > 0.01"
|
|
29
|
+
page: payments-oncall
|
|
30
|
+
checks:
|
|
31
|
+
liveness: GET /actuator/health/liveness
|
|
32
|
+
readiness: GET /actuator/health/readiness
|
|
33
|
+
dependencies:
|
|
34
|
+
- service: kafka
|
|
35
|
+
criticality: critical # the outbox holds, but nothing leaves the service
|
|
36
|
+
- service: stripe
|
|
37
|
+
criticality: critical # no acquirer, no authorization
|
|
38
|
+
- service: identity-service
|
|
39
|
+
criticality: degradable # cached introspection decisions carry a request
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Per-service C4. Written by an agent from the `loam adopt` brief, then curated.
|
|
2
|
+
//
|
|
3
|
+
// loam parses every `.likec4` file ALONE, so this document declares its own
|
|
4
|
+
// `specification` block; a renderer handed the whole tree at once would merge
|
|
5
|
+
// them and call every declaration a duplicate, which is what
|
|
6
|
+
// `likec4.config.json` scopes the root project to `architecture/` for.
|
|
7
|
+
specification {
|
|
8
|
+
element softwareSystem
|
|
9
|
+
element container
|
|
10
|
+
element database
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
model {
|
|
14
|
+
paymentService = softwareSystem 'payment-service' {
|
|
15
|
+
description 'Owns payment authorization/capture'
|
|
16
|
+
|
|
17
|
+
api = container 'api' {
|
|
18
|
+
description 'REST API'
|
|
19
|
+
technology 'Spring Boot'
|
|
20
|
+
}
|
|
21
|
+
domain = container 'domain' {
|
|
22
|
+
description 'Payment domain logic'
|
|
23
|
+
technology 'Java'
|
|
24
|
+
}
|
|
25
|
+
// The store is a container of THIS service, not a fleet-level peer. Drawn
|
|
26
|
+
// in the landscape it would be a system in its own right, available to be
|
|
27
|
+
// depended on — which is the claim `landscape.datastore-private` exists to
|
|
28
|
+
// refuse when only one service reaches it.
|
|
29
|
+
db = database 'db' {
|
|
30
|
+
description 'Payments store'
|
|
31
|
+
technology 'PostgreSQL'
|
|
32
|
+
}
|
|
33
|
+
outbox = database 'outbox' {
|
|
34
|
+
description 'Transactional outbox drained by the relay'
|
|
35
|
+
technology 'PostgreSQL'
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
api -> domain 'Uses'
|
|
39
|
+
domain -> db 'Reads/writes'
|
|
40
|
+
domain -> outbox 'Appends events in the state-change transaction'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// The service model carries everything the service touches — cross-boundary
|
|
44
|
+
// dependencies included, drawn with the edge the service actually has. The
|
|
45
|
+
// landscape carries only the boundary crossing; health.yaml's dependencies
|
|
46
|
+
// must resolve HERE (`health.dependency-unmodelled` otherwise), which is why
|
|
47
|
+
// all three of this service's declared dependencies appear below.
|
|
48
|
+
kafka = softwareSystem 'kafka' {
|
|
49
|
+
description 'Event backbone (platform)'
|
|
50
|
+
}
|
|
51
|
+
identityService = softwareSystem 'identity-service' {
|
|
52
|
+
description 'Token validation (degradable: cached decisions carry a request)'
|
|
53
|
+
}
|
|
54
|
+
stripe = softwareSystem 'stripe' {
|
|
55
|
+
description 'Card acquirer'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
paymentService.outbox -> kafka 'Relay publishes payment events'
|
|
59
|
+
paymentService.domain -> identityService 'Validates the caller token'
|
|
60
|
+
paymentService.domain -> stripe 'Authorizes and captures cards'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
views {
|
|
64
|
+
view payment_service of paymentService {
|
|
65
|
+
include *
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# API contract. Written by an agent from the `loam adopt` brief; forward-flow authors changes
|
|
2
|
+
# in the feature's own `specs/<svc>/openapi.yaml` delta and lets `loam archive` merge them here.
|
|
3
|
+
#
|
|
4
|
+
# Only the eight HTTP methods of a path item are read for operationIds — an id tucked inside a
|
|
5
|
+
# vendor extension does not exist as far as the spine is concerned, because a phantom id would
|
|
6
|
+
# mask a contract break. Two things are graded beyond form: every operation wants a response
|
|
7
|
+
# with a schema (`openapi.response-undescribed` otherwise — a contract that names an operation
|
|
8
|
+
# and says nothing about what it returns still sends the reader to the code), and every 4xx/5xx
|
|
9
|
+
# it declares wants a scenario that reaches it (`api.response-ungoverned`).
|
|
10
|
+
openapi: 3.1.0
|
|
11
|
+
info:
|
|
12
|
+
title: payment-service
|
|
13
|
+
version: "1.0"
|
|
14
|
+
paths:
|
|
15
|
+
/payments:
|
|
16
|
+
post:
|
|
17
|
+
operationId: authorizePayment
|
|
18
|
+
summary: Authorize a payment
|
|
19
|
+
requestBody:
|
|
20
|
+
required: true
|
|
21
|
+
content:
|
|
22
|
+
application/json:
|
|
23
|
+
schema:
|
|
24
|
+
$ref: '#/components/schemas/AuthorizationRequest'
|
|
25
|
+
responses:
|
|
26
|
+
"201":
|
|
27
|
+
description: Authorized
|
|
28
|
+
content:
|
|
29
|
+
application/json:
|
|
30
|
+
schema:
|
|
31
|
+
$ref: '#/components/schemas/Payment'
|
|
32
|
+
"409":
|
|
33
|
+
description: A different authorization already exists for this order
|
|
34
|
+
content:
|
|
35
|
+
application/json:
|
|
36
|
+
schema:
|
|
37
|
+
$ref: '#/components/schemas/Problem'
|
|
38
|
+
/payments/{id}/capture:
|
|
39
|
+
parameters:
|
|
40
|
+
- name: id
|
|
41
|
+
in: path
|
|
42
|
+
required: true
|
|
43
|
+
schema:
|
|
44
|
+
type: string
|
|
45
|
+
format: uuid
|
|
46
|
+
post:
|
|
47
|
+
operationId: capturePayment
|
|
48
|
+
summary: Capture an authorized payment
|
|
49
|
+
responses:
|
|
50
|
+
"200":
|
|
51
|
+
description: Captured
|
|
52
|
+
content:
|
|
53
|
+
application/json:
|
|
54
|
+
schema:
|
|
55
|
+
$ref: '#/components/schemas/Capture'
|
|
56
|
+
"404":
|
|
57
|
+
description: No such authorized payment
|
|
58
|
+
content:
|
|
59
|
+
application/json:
|
|
60
|
+
schema:
|
|
61
|
+
$ref: '#/components/schemas/Problem'
|
|
62
|
+
/payments/{id}/refund:
|
|
63
|
+
parameters:
|
|
64
|
+
- name: id
|
|
65
|
+
in: path
|
|
66
|
+
required: true
|
|
67
|
+
schema:
|
|
68
|
+
type: string
|
|
69
|
+
format: uuid
|
|
70
|
+
post:
|
|
71
|
+
operationId: refundPayment
|
|
72
|
+
summary: Refund a captured payment
|
|
73
|
+
responses:
|
|
74
|
+
"200":
|
|
75
|
+
description: Refunded
|
|
76
|
+
content:
|
|
77
|
+
application/json:
|
|
78
|
+
schema:
|
|
79
|
+
$ref: "#/components/schemas/Refund"
|
|
80
|
+
"409":
|
|
81
|
+
description: The payment was already refunded
|
|
82
|
+
content:
|
|
83
|
+
application/json:
|
|
84
|
+
schema:
|
|
85
|
+
$ref: "#/components/schemas/Problem"
|
|
86
|
+
|
|
87
|
+
components:
|
|
88
|
+
schemas:
|
|
89
|
+
AuthorizationRequest:
|
|
90
|
+
type: object
|
|
91
|
+
required: [ orderId, amount, currency ]
|
|
92
|
+
properties:
|
|
93
|
+
orderId:
|
|
94
|
+
type: string
|
|
95
|
+
amount:
|
|
96
|
+
type: integer
|
|
97
|
+
description: minor units
|
|
98
|
+
currency:
|
|
99
|
+
type: string
|
|
100
|
+
pattern: '^[A-Z]{3}$'
|
|
101
|
+
Payment:
|
|
102
|
+
type: object
|
|
103
|
+
required: [ paymentId, status ]
|
|
104
|
+
properties:
|
|
105
|
+
paymentId:
|
|
106
|
+
type: string
|
|
107
|
+
format: uuid
|
|
108
|
+
status:
|
|
109
|
+
type: string
|
|
110
|
+
enum: [ authorized, declined ]
|
|
111
|
+
Capture:
|
|
112
|
+
type: object
|
|
113
|
+
required: [ paymentId, capturedAmount ]
|
|
114
|
+
properties:
|
|
115
|
+
paymentId:
|
|
116
|
+
type: string
|
|
117
|
+
format: uuid
|
|
118
|
+
capturedAmount:
|
|
119
|
+
type: integer
|
|
120
|
+
description: minor units
|
|
121
|
+
# RFC 9457. One shared shape for every refusal, so a client parses failures once —
|
|
122
|
+
# and so the 409 and 404 above declare a schema rather than a bare description.
|
|
123
|
+
Problem:
|
|
124
|
+
type: object
|
|
125
|
+
required: [ type, title, status ]
|
|
126
|
+
properties:
|
|
127
|
+
type:
|
|
128
|
+
type: string
|
|
129
|
+
format: uri
|
|
130
|
+
title:
|
|
131
|
+
type: string
|
|
132
|
+
status:
|
|
133
|
+
type: integer
|
|
134
|
+
detail:
|
|
135
|
+
type: string
|
|
136
|
+
Refund:
|
|
137
|
+
type: object
|
|
138
|
+
required:
|
|
139
|
+
- paymentId
|
|
140
|
+
- refundedAmount
|
|
141
|
+
- refundedAt
|
|
142
|
+
properties:
|
|
143
|
+
paymentId:
|
|
144
|
+
type: string
|
|
145
|
+
format: uuid
|
|
146
|
+
refundedAmount:
|
|
147
|
+
type: integer
|
|
148
|
+
description: minor units
|
|
149
|
+
refundedAt:
|
|
150
|
+
type: string
|
|
151
|
+
format: date-time
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
service: payment-service
|
|
3
|
+
status: draft
|
|
4
|
+
owner: payments-team
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# payment-service — runbook
|
|
8
|
+
|
|
9
|
+
Frontmatter here is read by nothing: `loam list` tracks that this file EXISTS, and no check
|
|
10
|
+
grades a field in it. What is written above is a note to the next reader, not a claim loam will
|
|
11
|
+
catch when it goes stale.
|
|
12
|
+
|
|
13
|
+
## Deploy
|
|
14
|
+
- Pipeline: `.gitlab-ci.yml` -> `deploy:prod` (manual gate).
|
|
15
|
+
- Config: `application.yml`; secrets via Vault path `secret/payment-service`.
|
|
16
|
+
|
|
17
|
+
## Health
|
|
18
|
+
- Liveness: `GET /actuator/health/liveness`
|
|
19
|
+
- Readiness: `GET /actuator/health/readiness` (checks db + kafka)
|
|
20
|
+
- The SLIs and the alert are declared in `health.yaml`, and `arch.spec.md` carries the
|
|
21
|
+
requirement that says what each one is for. A signal nothing covers is `health.uncovered`.
|
|
22
|
+
|
|
23
|
+
## Common incidents
|
|
24
|
+
- **Outbox relay lag** -> events delayed, and every consumer downstream of `payment.events`
|
|
25
|
+
falls behind with it. Check the `outbox_pending` gauge; restart the relay. The payments
|
|
26
|
+
themselves are unaffected: the outbox is what makes the state change and its event one
|
|
27
|
+
transaction, so nothing is lost, only late.
|
|
28
|
+
- **DB connection exhaustion** -> 503s. Check pool metrics; scale or fix a leak.
|
|
29
|
+
- **Acquirer timeouts** -> authorizations in an unknown state. Do not retry by hand: the
|
|
30
|
+
reconciliation job replays with the original idempotency key, which is the only path that
|
|
31
|
+
cannot double-charge.
|
|
32
|
+
- **identity-service unavailable** -> declared `degradable` in `health.yaml`: cached
|
|
33
|
+
introspection decisions carry requests for their remaining TTL, and authorization starts
|
|
34
|
+
failing closed once the cache empties.
|
|
35
|
+
|
|
36
|
+
## Escalation
|
|
37
|
+
On-call channel: `#payments-oncall`.
|