@dogfood-lab/schemas 1.4.0 → 1.6.0
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/README.md +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/payload-types.d.ts +401 -0
- package/dist/payload-types.d.ts.map +1 -0
- package/dist/payload-types.js +161 -0
- package/dist/payload-types.js.map +1 -0
- package/package.json +2 -2
- package/src/json/dogfood-record-submission.schema.json +11 -5
- package/src/json/dogfood-record.schema.json +45 -6
- package/src/json/policy.schema.json +11 -1
package/README.md
CHANGED
|
@@ -75,6 +75,24 @@ import recordSchema from '@dogfood-lab/schemas/json/dogfood-record.schema.json'
|
|
|
75
75
|
|
|
76
76
|
`$id` is a contract field. Changes that consumers should treat as contract changes bump the monorepo's lockstep version.
|
|
77
77
|
|
|
78
|
+
## Schema versioning
|
|
79
|
+
|
|
80
|
+
Payloads that carry a `schema_version` are gated by **MAJOR range**, not exact match. The accepted ranges live in one place — `SUPPORTED_SCHEMA_VERSIONS` (`src/schema-versions.ts`), which `@dogfood-lab/verify` imports to drive the gate and to stamp the persisted record's `schema_version`:
|
|
81
|
+
|
|
82
|
+
| Field | Meaning |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `current` | the version this build emits for the contract |
|
|
85
|
+
| `minMajor` | lowest MAJOR accepted (inclusive) |
|
|
86
|
+
| `maxMajor` | highest MAJOR accepted (inclusive) |
|
|
87
|
+
|
|
88
|
+
The gate compares the payload's MAJOR against `[minMajor, maxMajor]`:
|
|
89
|
+
|
|
90
|
+
- **MAJOR inside the range** (any patch/minor) → **accepted**.
|
|
91
|
+
- **MAJOR above `maxMajor`** → rejected `CONTRACT_SCHEMA_TOO_NEW` — the payload was emitted against a newer contract than this build understands. **Operator action: upgrade testing-os.**
|
|
92
|
+
- **MAJOR below `minMajor`** → rejected `CONTRACT_SCHEMA_TOO_OLD` — the payload predates the supported contract. **Operator action: re-emit against the current contract.**
|
|
93
|
+
|
|
94
|
+
The contracts that carry `schema_version` are `record`, `recordSubmission`, `finding`, `pattern`, `recommendation`, `doctrine`, and the `agentOutput` swarm envelope. **`policy` and `scenario` deliberately carry no `schema_version`** and are exempt from the gate — the gate only fires on payloads that declare one. See the [error code reference](https://dogfood-lab.github.io/testing-os/handbook/error-codes/) for how the `CONTRACT_SCHEMA_TOO_*` rejections surface to a consumer.
|
|
95
|
+
|
|
78
96
|
## Docs
|
|
79
97
|
|
|
80
98
|
📖 Full handbook: **<https://dogfood-lab.github.io/testing-os/handbook/>**
|
package/dist/index.d.ts
CHANGED
|
@@ -43,4 +43,5 @@ export declare function _loadSchemaForTests(filename: string, dirOverride?: stri
|
|
|
43
43
|
export { compileSchema, validatePayload, createAjv, _resetValidatorCacheForTests, _schemasModuleInstanceCount, type ValidationError, type ValidationResult, } from './validate.js';
|
|
44
44
|
export { SUPPORTED_SCHEMA_VERSIONS, type SupportedSchemaVersion, type SupportedSchemaContract, } from './schema-versions.js';
|
|
45
45
|
export { PRODUCT_SURFACES, EXECUTION_MODES, EVIDENCE_KINDS, type ProductSurface, type ExecutionMode, type EvidenceKind, } from './enums.js';
|
|
46
|
+
export { EXAMPLE_PAYLOADS, type Submission, type Record, type Finding, type ScenarioResult, type StepResult, type ScenarioEvidence, type Ref, type Source, type Timing, type CiCheck, type CiCheckKind, type CiCheckStatus, type Verdict, type StepStatus, type RecordOverallVerdict, type Verification, type ProvenanceRemediation, type FindingStatus, type JourneyStage, type IssueKind, type RootCauseKind, type RemediationKind, type TransferScope, type FindingEvidence, type FindingEvidenceKind, type FixRef, type FixRefKind, type FindingDerived, type FindingReview, type ReviewAction, type RejectReason, type FindingLineage, type FindingInvalidation, } from './payload-types.js';
|
|
46
47
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6DA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oBAAoB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,EAAE,UAA+C,CAAC;AAC3E,eAAO,MAAM,sBAAsB,EAAE,UAA0D,CAAC;AAChG,eAAO,MAAM,aAAa,EAAE,UAAgD,CAAC;AAC7E,eAAO,MAAM,aAAa,EAAE,UAAgD,CAAC;AAC7E,eAAO,MAAM,oBAAoB,EAAE,UAAuD,CAAC;AAC3F,eAAO,MAAM,cAAc,EAAE,UAAiD,CAAC;AAC/E,eAAO,MAAM,YAAY,EAAE,UAAuC,CAAC;AACnE,eAAO,MAAM,cAAc,EAAE,UAAyC,CAAC;AAEvE,eAAO,MAAM,UAAU;;;;;;;;;CASb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAEtF;AAED,OAAO,EACL,aAAa,EACb,eAAe,EACf,SAAS,EACT,4BAA4B,EAC5B,2BAA2B,EAC3B,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6DA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oBAAoB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,YAAY,EAAE,UAA+C,CAAC;AAC3E,eAAO,MAAM,sBAAsB,EAAE,UAA0D,CAAC;AAChG,eAAO,MAAM,aAAa,EAAE,UAAgD,CAAC;AAC7E,eAAO,MAAM,aAAa,EAAE,UAAgD,CAAC;AAC7E,eAAO,MAAM,oBAAoB,EAAE,UAAuD,CAAC;AAC3F,eAAO,MAAM,cAAc,EAAE,UAAiD,CAAC;AAC/E,eAAO,MAAM,YAAY,EAAE,UAAuC,CAAC;AACnE,eAAO,MAAM,cAAc,EAAE,UAAyC,CAAC;AAEvE,eAAO,MAAM,UAAU;;;;;;;;;CASb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,UAAU,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CAEtF;AAED,OAAO,EACL,aAAa,EACb,eAAe,EACf,SAAS,EACT,4BAA4B,EAC5B,2BAA2B,EAC3B,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAMpB,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,GAAG,EACR,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -85,4 +85,9 @@ export function _loadSchemaForTests(filename, dirOverride) {
|
|
|
85
85
|
export { compileSchema, validatePayload, createAjv, _resetValidatorCacheForTests, _schemasModuleInstanceCount, } from './validate.js';
|
|
86
86
|
export { SUPPORTED_SCHEMA_VERSIONS, } from './schema-versions.js';
|
|
87
87
|
export { PRODUCT_SURFACES, EXECUTION_MODES, EVIDENCE_KINDS, } from './enums.js';
|
|
88
|
+
// FT-h — hand-authored TypeScript interfaces for the contract payload SHAPES,
|
|
89
|
+
// so TS consumers get compile-time safety on the envelope (the schema OBJECTS
|
|
90
|
+
// + validatePayload only catch shape errors at runtime). Kept in sync with the
|
|
91
|
+
// JSON schemas; each interface carries a `Mirrors:` pointer to its source.
|
|
92
|
+
export { EXAMPLE_PAYLOADS, } from './payload-types.js';
|
|
88
93
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,SAAS,IAAI,CAAC,QAAgB,EAAE,WAAoB;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,uDAAuD,QAAQ,QAAQ,IAAI,MACxE,CAAW,CAAC,OACf,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IACvC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wDAAwD,QAAQ,QAAQ,IAAI,iEACzE,CAAW,CAAC,OACf,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAcD,MAAM,CAAC,MAAM,YAAY,GAAe,IAAI,CAAC,4BAA4B,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,sBAAsB,GAAe,IAAI,CAAC,uCAAuC,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,aAAa,GAAe,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAe,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,oBAAoB,GAAe,IAAI,CAAC,oCAAoC,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,cAAc,GAAe,IAAI,CAAC,8BAA8B,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAe,IAAI,CAAC,oBAAoB,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,cAAc,GAAe,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,YAAY;IACpB,gBAAgB,EAAE,sBAAsB;IACxC,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,aAAa;IACtB,cAAc,EAAE,oBAAoB;IACpC,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;CAChB,CAAC;AAIX;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAoB;IACxE,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,OAAO,EACL,aAAa,EACb,eAAe,EACf,SAAS,EACT,4BAA4B,EAC5B,2BAA2B,GAG5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,GAG1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,GAIf,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,SAAS,IAAI,CAAC,QAAgB,EAAE,WAAoB;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,uDAAuD,QAAQ,QAAQ,IAAI,MACxE,CAAW,CAAC,OACf,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IACvC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wDAAwD,QAAQ,QAAQ,IAAI,iEACzE,CAAW,CAAC,OACf,EAAE,CACH,CAAC;IACJ,CAAC;AACH,CAAC;AAcD,MAAM,CAAC,MAAM,YAAY,GAAe,IAAI,CAAC,4BAA4B,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,sBAAsB,GAAe,IAAI,CAAC,uCAAuC,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,aAAa,GAAe,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAe,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,oBAAoB,GAAe,IAAI,CAAC,oCAAoC,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,cAAc,GAAe,IAAI,CAAC,8BAA8B,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAe,IAAI,CAAC,oBAAoB,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,cAAc,GAAe,IAAI,CAAC,sBAAsB,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,YAAY;IACpB,gBAAgB,EAAE,sBAAsB;IACxC,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,aAAa;IACtB,cAAc,EAAE,oBAAoB;IACpC,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,QAAQ,EAAE,cAAc;CAChB,CAAC;AAIX;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAoB;IACxE,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,OAAO,EACL,aAAa,EACb,eAAe,EACf,SAAS,EACT,4BAA4B,EAC5B,2BAA2B,GAG5B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,yBAAyB,GAG1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,cAAc,GAIf,MAAM,YAAY,CAAC;AAEpB,8EAA8E;AAC9E,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,OAAO,EACL,gBAAgB,GAkCjB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-authored TypeScript interfaces for the contract payload shapes.
|
|
3
|
+
*
|
|
4
|
+
* FT-h (Wave, HIGH, consumability). The package exports the JSON-schema
|
|
5
|
+
* OBJECTS, the three full-set enum unions, and `validatePayload`, but no
|
|
6
|
+
* TypeScript interface for the actual payload SHAPES. A TS consumer that
|
|
7
|
+
* builds a submission, reads a persisted record, or constructs a finding got
|
|
8
|
+
* zero compile-time safety on the envelope — `validatePayload` only catches
|
|
9
|
+
* the mistake at runtime, after the bad object already flowed through typed
|
|
10
|
+
* code as `unknown`/`any`.
|
|
11
|
+
*
|
|
12
|
+
* These interfaces give consumers a typed shape to assert against at author
|
|
13
|
+
* time. They are HAND-MAINTAINED to mirror the JSON schemas — there is no
|
|
14
|
+
* codegen step — so each interface and nested type carries a `Mirrors:`
|
|
15
|
+
* pointer to its source schema, and the {@link EXAMPLE_PAYLOADS} consts at the
|
|
16
|
+
* bottom are `satisfies`-checked so `tsc --build` (which CI runs via
|
|
17
|
+
* `npm run verify` → `npm run build`) goes RED the moment an interface drifts
|
|
18
|
+
* from a representative payload. The companion vitest
|
|
19
|
+
* (`test/payload-types.test.ts`) closes the other half of the loop: it pushes
|
|
20
|
+
* those same examples through `validatePayload` and asserts the JSON schema
|
|
21
|
+
* AGREES they are valid. Interface drift in EITHER direction is caught.
|
|
22
|
+
*
|
|
23
|
+
* Reused enum unions: enum-typed fields reference the exported
|
|
24
|
+
* {@link ProductSurface} / {@link ExecutionMode} / {@link EvidenceKind} unions
|
|
25
|
+
* rather than re-typing the literals, so those fields stay sealed to the same
|
|
26
|
+
* single source the cross-contract enum seal enforces on the JSON side.
|
|
27
|
+
*
|
|
28
|
+
* SCOPE — the four payloads FT-h names: {@link Submission},
|
|
29
|
+
* {@link ScenarioResult}, {@link Record}, {@link Finding}. The other four
|
|
30
|
+
* contract schemas (pattern, recommendation, doctrine, policy) are out of
|
|
31
|
+
* scope for this slice and intentionally not modelled here; add them the same
|
|
32
|
+
* way (interface + `Mirrors:` pointer + a `satisfies` example) when a consumer
|
|
33
|
+
* needs them.
|
|
34
|
+
*/
|
|
35
|
+
import type { ProductSurface, ExecutionMode, EvidenceKind } from './enums.js';
|
|
36
|
+
/** Scenario- and run-level verdict. Mirrors the `verdict` / `overall_verdict` enum. */
|
|
37
|
+
export type Verdict = 'pass' | 'fail' | 'blocked' | 'partial';
|
|
38
|
+
/** Per-step status. Mirrors `scenario_results[].step_results[].status`. */
|
|
39
|
+
export type StepStatus = 'pass' | 'fail' | 'blocked' | 'skip' | 'partial';
|
|
40
|
+
/** Machine CI check kind. Mirrors `ci_checks[].kind`. */
|
|
41
|
+
export type CiCheckKind = 'test' | 'coverage' | 'lint' | 'security' | 'build' | 'other';
|
|
42
|
+
/** Machine CI check status. Mirrors `ci_checks[].status`. */
|
|
43
|
+
export type CiCheckStatus = 'pass' | 'fail' | 'skip';
|
|
44
|
+
/** Git ref of the work under test. Mirrors the `ref` object. */
|
|
45
|
+
export interface Ref {
|
|
46
|
+
/** Branch name, if applicable. */
|
|
47
|
+
branch?: string;
|
|
48
|
+
/** 40-char lowercase-hex commit SHA. Schema pattern: `^[0-9a-f]{40}$`. */
|
|
49
|
+
commit_sha: string;
|
|
50
|
+
/** Release version tag if applicable. */
|
|
51
|
+
version?: string;
|
|
52
|
+
}
|
|
53
|
+
/** SCM provider that ran the workflow. Mirrors the `source.provider` enum. */
|
|
54
|
+
export type SourceProvider = 'github' | 'gitlab';
|
|
55
|
+
/** SCM provenance of the run. Mirrors the `source` object. */
|
|
56
|
+
export interface Source {
|
|
57
|
+
/** SCM provider — 'github' (GitHub Actions) or 'gitlab' (GitLab CI). */
|
|
58
|
+
provider: SourceProvider;
|
|
59
|
+
/** Workflow filename that produced the submission (e.g. a GitHub Actions YAML or '.gitlab-ci.yml'). */
|
|
60
|
+
workflow: string;
|
|
61
|
+
/** Provider-native run ID: a GitHub Actions run ID or a GitLab pipeline/job ID. */
|
|
62
|
+
provider_run_id: string;
|
|
63
|
+
/** Run attempt number. Schema default is 1. */
|
|
64
|
+
attempt?: number;
|
|
65
|
+
/** URL to the provider run. Schema format: uri. */
|
|
66
|
+
run_url: string;
|
|
67
|
+
/** Username that triggered the workflow. */
|
|
68
|
+
actor?: string;
|
|
69
|
+
}
|
|
70
|
+
/** Wall-clock timing of the run. Mirrors the `timing` object. */
|
|
71
|
+
export interface Timing {
|
|
72
|
+
/** ISO-8601 date-time the run started. */
|
|
73
|
+
started_at: string;
|
|
74
|
+
/** ISO-8601 date-time the run finished. */
|
|
75
|
+
finished_at: string;
|
|
76
|
+
/** Duration in milliseconds. */
|
|
77
|
+
duration_ms?: number;
|
|
78
|
+
}
|
|
79
|
+
/** A machine-evaluated CI result. Mirrors a `ci_checks[]` element. */
|
|
80
|
+
export interface CiCheck {
|
|
81
|
+
id: string;
|
|
82
|
+
kind: CiCheckKind;
|
|
83
|
+
status: CiCheckStatus;
|
|
84
|
+
/** Numeric result (test count, coverage %, etc.). */
|
|
85
|
+
value?: number;
|
|
86
|
+
/** Policy threshold if applicable. */
|
|
87
|
+
threshold?: number;
|
|
88
|
+
}
|
|
89
|
+
/** A single per-step execution result. Mirrors `scenario_results[].step_results[]`. */
|
|
90
|
+
export interface StepResult {
|
|
91
|
+
/** Must match a step.id from the scenario definition. Pattern: `^[a-z0-9][a-z0-9-]*$`. */
|
|
92
|
+
step_id: string;
|
|
93
|
+
status: StepStatus;
|
|
94
|
+
notes?: string;
|
|
95
|
+
}
|
|
96
|
+
/** A piece of evidence attached to a scenario result. Mirrors `scenario_results[].evidence[]`. */
|
|
97
|
+
export interface ScenarioEvidence {
|
|
98
|
+
/** Evidence kind — reuses the sealed full-set {@link EvidenceKind} union. */
|
|
99
|
+
kind: EvidenceKind;
|
|
100
|
+
/** Evidence URL. Schema format: uri. */
|
|
101
|
+
url: string;
|
|
102
|
+
description?: string;
|
|
103
|
+
/** ISO-8601 date-time when this evidence URL becomes unavailable. */
|
|
104
|
+
expires_at?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* One scenario's dogfood evidence.
|
|
108
|
+
*
|
|
109
|
+
* Mirrors the `scenario_results[]` item shape shared by the submission and the
|
|
110
|
+
* persisted record. `product_surface` / `execution_mode` reuse the sealed
|
|
111
|
+
* full-set enum unions.
|
|
112
|
+
*/
|
|
113
|
+
export interface ScenarioResult {
|
|
114
|
+
/** Stable ID matching a scenario definition in the source repo. */
|
|
115
|
+
scenario_id: string;
|
|
116
|
+
scenario_name?: string;
|
|
117
|
+
/** Semver. Schema pattern: `^\d+\.\d+\.\d+$`. */
|
|
118
|
+
scenario_version?: string;
|
|
119
|
+
product_surface: ProductSurface;
|
|
120
|
+
execution_mode: ExecutionMode;
|
|
121
|
+
/** Human attester ID. Verifier enforces presence when execution_mode is human or mixed. */
|
|
122
|
+
attested_by?: string;
|
|
123
|
+
verdict: Verdict;
|
|
124
|
+
/** Required when verdict is blocked. Verifier enforces. */
|
|
125
|
+
blocking_reason?: string;
|
|
126
|
+
/** Per-step execution results. Schema minItems: 1. */
|
|
127
|
+
step_results: StepResult[];
|
|
128
|
+
evidence?: ScenarioEvidence[];
|
|
129
|
+
notes?: string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Source-authored dogfood submission payload — what a consumer repo emits via
|
|
133
|
+
* `repository_dispatch`. Carries NO verifier-owned fields (no `verification`,
|
|
134
|
+
* no `policy_version`); `overall_verdict` is a flat {@link Verdict} the source
|
|
135
|
+
* PROPOSES (the verifier may confirm or downgrade, never upgrade).
|
|
136
|
+
*
|
|
137
|
+
* Mirrors: dogfood-record-submission.schema.json.
|
|
138
|
+
*/
|
|
139
|
+
export interface Submission {
|
|
140
|
+
/** Semver of the submission schema. Schema pattern: `^\d+\.\d+\.\d+$`. */
|
|
141
|
+
schema_version: string;
|
|
142
|
+
/** Unique run identifier. Schema pattern: `^[A-Za-z0-9_-]+$` (filesystem-path-safe). */
|
|
143
|
+
run_id: string;
|
|
144
|
+
/** Full org/repo name. Schema pattern: `^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$`. */
|
|
145
|
+
repo: string;
|
|
146
|
+
ref: Ref;
|
|
147
|
+
source: Source;
|
|
148
|
+
timing: Timing;
|
|
149
|
+
/** Optional — not all dogfood runs include CI. */
|
|
150
|
+
ci_checks?: CiCheck[];
|
|
151
|
+
/** Dogfood evidence. Schema minItems: 1. */
|
|
152
|
+
scenario_results: ScenarioResult[];
|
|
153
|
+
/** Source-proposed verdict (flat). */
|
|
154
|
+
overall_verdict: Verdict;
|
|
155
|
+
notes?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The persisted record's `overall_verdict` object. Unlike the submission's
|
|
159
|
+
* flat verdict, the record nests proposed-vs-verified to record the verifier's
|
|
160
|
+
* decision. Mirrors `overall_verdict` in dogfood-record.schema.json.
|
|
161
|
+
*/
|
|
162
|
+
export interface RecordOverallVerdict {
|
|
163
|
+
/** Verdict as proposed by the source repo. */
|
|
164
|
+
proposed: Verdict;
|
|
165
|
+
/** Final verdict after central verification. */
|
|
166
|
+
verified: Verdict;
|
|
167
|
+
/** True if verifier downgraded the proposed verdict. Schema default: false. */
|
|
168
|
+
downgraded?: boolean;
|
|
169
|
+
/** Machine-readable reasons if verifier downgraded. */
|
|
170
|
+
downgrade_reasons?: string[];
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Provenance-remediation metadata — present when a record's provenance could
|
|
174
|
+
* not be auto-confirmed but was manually stub-verified. Mirrors
|
|
175
|
+
* `verification.provenance_remediation` in dogfood-record.schema.json.
|
|
176
|
+
*/
|
|
177
|
+
export interface ProvenanceRemediation {
|
|
178
|
+
status?: 'stub_verified';
|
|
179
|
+
/** Schema maxLength: 500. */
|
|
180
|
+
note?: string;
|
|
181
|
+
remediated_at: string;
|
|
182
|
+
/** Tri-state: the original boolean, or null when it was never evaluated. */
|
|
183
|
+
original_provenance_confirmed?: boolean | null;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Tamper-evident hash-chain metadata stamped by the persist layer when a record
|
|
187
|
+
* is written. Mirrors the OPTIONAL `integrity` object in
|
|
188
|
+
* dogfood-record.schema.json — records persisted before the integrity chain
|
|
189
|
+
* existed have no integrity block, so the field is optional on {@link Record}.
|
|
190
|
+
* The digest is computed over the record with this block removed (you cannot
|
|
191
|
+
* hash the digest into itself).
|
|
192
|
+
*/
|
|
193
|
+
export interface RecordIntegrity {
|
|
194
|
+
/** Lowercase sha256 hex (64 chars) of the canonicalized record without the integrity block. Schema pattern: `^[0-9a-f]{64}$`. */
|
|
195
|
+
submission_digest: string;
|
|
196
|
+
/** The previous entry's submission_digest, or 64 zeros (genesis) for the first entry. Schema pattern: `^[0-9a-f]{64}$`. */
|
|
197
|
+
prev_digest: string;
|
|
198
|
+
/** Monotonic chain position, starting at 0. Schema minimum: 0. */
|
|
199
|
+
seq: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Verifier-owned verification block. Mirrors `verification` in
|
|
203
|
+
* dogfood-record.schema.json. Never authored by source repos.
|
|
204
|
+
*/
|
|
205
|
+
export interface Verification {
|
|
206
|
+
/** Final outcome. No pending state in persisted records. */
|
|
207
|
+
status: 'accepted' | 'rejected';
|
|
208
|
+
verified_at: string;
|
|
209
|
+
/** True if the provider API (GitHub Actions or GitLab CI, per source.provider) confirmed the source run exists and matches claims. */
|
|
210
|
+
provenance_confirmed: boolean;
|
|
211
|
+
/** True if submission passed JSON Schema validation. */
|
|
212
|
+
schema_valid: boolean;
|
|
213
|
+
/** True if record satisfies all applicable policy rules. */
|
|
214
|
+
policy_valid: boolean;
|
|
215
|
+
/** Machine-readable rejection reasons. Empty/absent if accepted. */
|
|
216
|
+
rejection_reasons?: string[];
|
|
217
|
+
provenance_remediation?: ProvenanceRemediation;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Canonical persisted record written by the central verifier — all
|
|
221
|
+
* source-authored fields plus verifier-owned ones (`policy_version`,
|
|
222
|
+
* `verification`, and the nested {@link RecordOverallVerdict}). Never authored
|
|
223
|
+
* by source repos.
|
|
224
|
+
*
|
|
225
|
+
* Mirrors: dogfood-record.schema.json.
|
|
226
|
+
*
|
|
227
|
+
* Named `Record` to match the schema title; this shadows the TS global
|
|
228
|
+
* `Record<K, V>` utility type WITHIN modules that import it, which is the
|
|
229
|
+
* intended contract-first naming. Modules needing the utility can alias on
|
|
230
|
+
* import (`import type { Record as DogfoodRecord }`).
|
|
231
|
+
*/
|
|
232
|
+
export interface Record {
|
|
233
|
+
/** Semver of the persisted record schema. */
|
|
234
|
+
schema_version: string;
|
|
235
|
+
/** Semver of the policy this record was evaluated against. Set by verifier. */
|
|
236
|
+
policy_version: string;
|
|
237
|
+
run_id: string;
|
|
238
|
+
repo: string;
|
|
239
|
+
ref: Ref;
|
|
240
|
+
source: Source;
|
|
241
|
+
timing: Timing;
|
|
242
|
+
ci_checks?: CiCheck[];
|
|
243
|
+
scenario_results: ScenarioResult[];
|
|
244
|
+
overall_verdict: RecordOverallVerdict;
|
|
245
|
+
verification: Verification;
|
|
246
|
+
notes?: string;
|
|
247
|
+
/** Tamper-evident hash-chain metadata stamped at persist. Optional — absent on pre-chain records. */
|
|
248
|
+
integrity?: RecordIntegrity;
|
|
249
|
+
}
|
|
250
|
+
/** Finding lifecycle status. Mirrors `status`. */
|
|
251
|
+
export type FindingStatus = 'candidate' | 'reviewed' | 'accepted' | 'rejected';
|
|
252
|
+
/** Where in the product experience the lesson was observed. Mirrors `journey_stage`. */
|
|
253
|
+
export type JourneyStage = 'install' | 'setup' | 'first_run' | 'core_loop' | 'export' | 'publish' | 'recovery' | 'integration' | 'verification' | 'rollout';
|
|
254
|
+
/** What visibly went wrong. Mirrors `issue_kind`. */
|
|
255
|
+
export type IssueKind = 'entrypoint_truth' | 'interface_assumption' | 'docs_drift' | 'schema_mismatch' | 'build_output_mismatch' | 'flag_contract_mismatch' | 'evidence_insufficiency' | 'evidence_overconstraint' | 'policy_mismatch' | 'freshness_miscalibration' | 'read_after_write_timing' | 'provenance_gap' | 'execution_mode_mismatch' | 'surface_misclassification' | 'ux_discoverability' | 'verification_gap' | 'dispatch_format' | 'concurrency_conflict' | 'process_lifecycle';
|
|
256
|
+
/** Why it actually happened. Mirrors `root_cause_kind`. */
|
|
257
|
+
export type RootCauseKind = 'contract_drift' | 'docs_code_drift' | 'surface_misclassification' | 'missing_precondition' | 'policy_overconstraint' | 'policy_underconstraint' | 'build_config_error' | 'interface_assumption_error' | 'timing_race' | 'tooling_gap' | 'human_process_gap' | 'schema_alignment_failure' | 'dispatch_encoding_error' | 'process_model_mismatch';
|
|
258
|
+
/** What kind of fix resolved it. Mirrors `remediation_kind`. */
|
|
259
|
+
export type RemediationKind = 'docs_change' | 'scenario_change' | 'policy_calibration' | 'schema_fix' | 'build_config_fix' | 'entrypoint_fix' | 'verification_fix' | 'classification_fix' | 'retry_logic' | 'evidence_requirement_change' | 'workflow_change' | 'dispatch_fix' | 'process_fix';
|
|
260
|
+
/**
|
|
261
|
+
* How far the lesson should travel. Mirrors the finding `transfer_scope` enum
|
|
262
|
+
* (the FULL 5-value set — NOT the deliberate 3-value doctrine subset).
|
|
263
|
+
*/
|
|
264
|
+
export type TransferScope = 'repo_local' | 'surface_local' | 'surface_archetype' | 'execution_mode' | 'org_wide';
|
|
265
|
+
/** Type of evidence supporting a finding. Mirrors `evidence[].evidence_kind`. */
|
|
266
|
+
export type FindingEvidenceKind = 'record' | 'scenario_result' | 'ci_check' | 'policy' | 'artifact' | 'doc' | 'rejection';
|
|
267
|
+
/** A structured evidence binding on a finding. Mirrors `evidence[]`. */
|
|
268
|
+
export interface FindingEvidence {
|
|
269
|
+
evidence_kind: FindingEvidenceKind;
|
|
270
|
+
/** Run ID of the source record. */
|
|
271
|
+
record_id?: string;
|
|
272
|
+
/** Scenario ID if evidence is from a scenario result. */
|
|
273
|
+
scenario_id?: string;
|
|
274
|
+
/** Path or URL to an artifact. */
|
|
275
|
+
artifact_ref?: string;
|
|
276
|
+
/** Path to the policy file. */
|
|
277
|
+
policy_ref?: string;
|
|
278
|
+
/** Path to a documentation file. */
|
|
279
|
+
doc_ref?: string;
|
|
280
|
+
/** Schema maxLength: 500. */
|
|
281
|
+
note?: string;
|
|
282
|
+
}
|
|
283
|
+
/** Type of fix reference. Mirrors `fix_refs[].ref_kind`. */
|
|
284
|
+
export type FixRefKind = 'commit' | 'pr' | 'doc' | 'policy_change' | 'scenario_change' | 'workflow_change';
|
|
285
|
+
/** A link to a concrete repair action. Mirrors `fix_refs[]`. */
|
|
286
|
+
export interface FixRef {
|
|
287
|
+
ref_kind: FixRefKind;
|
|
288
|
+
/** Commit SHA, PR URL, file path, etc. */
|
|
289
|
+
ref: string;
|
|
290
|
+
/** Schema maxLength: 500. */
|
|
291
|
+
note?: string;
|
|
292
|
+
}
|
|
293
|
+
/** Derivation metadata — present when a finding was machine-generated. Mirrors `derived`. */
|
|
294
|
+
export interface FindingDerived {
|
|
295
|
+
method: 'deterministic_rule';
|
|
296
|
+
/** Pattern: `^rule-[a-z0-9][a-z0-9-]*$`. */
|
|
297
|
+
rule_id: string;
|
|
298
|
+
derived_at: string;
|
|
299
|
+
/** Schema minLength: 10, maxLength: 1000. */
|
|
300
|
+
rationale: string;
|
|
301
|
+
}
|
|
302
|
+
/** The most recent review action taken on a finding. Mirrors `review.last_action`. */
|
|
303
|
+
export type ReviewAction = 'review' | 'accept' | 'reject' | 'edit' | 'merge' | 'reopen' | 'invalidate' | 'supersede';
|
|
304
|
+
/** Structured reject reason. Mirrors `review.reject_reason`. */
|
|
305
|
+
export type RejectReason = 'insufficient_evidence' | 'duplicate' | 'classification_error' | 'not_portable' | 'noise' | 'source_truth_changed' | 'merged_into_canonical';
|
|
306
|
+
/** Current state of the most recent review action. Mirrors `review`. */
|
|
307
|
+
export interface FindingReview {
|
|
308
|
+
reviewed_by?: string;
|
|
309
|
+
reviewed_at?: string;
|
|
310
|
+
/** Schema maxLength: 1000. */
|
|
311
|
+
decision_reason?: string;
|
|
312
|
+
/** Schema maxLength: 2000. */
|
|
313
|
+
review_notes?: string;
|
|
314
|
+
last_action?: ReviewAction;
|
|
315
|
+
/**
|
|
316
|
+
* Structured reject reason. The schema's `allOf` makes this REQUIRED when
|
|
317
|
+
* `status` is `rejected` — that conditional cannot be expressed in a plain
|
|
318
|
+
* interface, so callers building a rejected finding must populate it (the
|
|
319
|
+
* runtime `validatePayload` check is what enforces the conditional).
|
|
320
|
+
*/
|
|
321
|
+
reject_reason?: RejectReason;
|
|
322
|
+
}
|
|
323
|
+
/** Merge and supersession lineage. Mirrors `lineage`. */
|
|
324
|
+
export interface FindingLineage {
|
|
325
|
+
/** Finding IDs merged into this canonical finding. */
|
|
326
|
+
merged_from?: string[];
|
|
327
|
+
/** Finding ID that supersedes this one. */
|
|
328
|
+
superseded_by?: string;
|
|
329
|
+
}
|
|
330
|
+
/** Invalidation metadata — present when an accepted finding is no longer trustworthy. Mirrors `invalidation`. */
|
|
331
|
+
export interface FindingInvalidation {
|
|
332
|
+
is_invalidated: boolean;
|
|
333
|
+
invalidated_at: string;
|
|
334
|
+
/** Review event ID that triggered the invalidation. */
|
|
335
|
+
invalidated_by?: string;
|
|
336
|
+
/** Schema minLength: 5, maxLength: 1000. */
|
|
337
|
+
reason: string;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* A reviewed, evidence-backed lesson extracted from one or more dogfood runs —
|
|
341
|
+
* the smallest durable unit of reusable learning. `product_surface` /
|
|
342
|
+
* `execution_mode` reuse the sealed full-set enum unions.
|
|
343
|
+
*
|
|
344
|
+
* Mirrors: dogfood-finding.schema.json. The schema additionally enforces an
|
|
345
|
+
* `allOf` conditional (status `rejected` ⇒ `review.reject_reason` required)
|
|
346
|
+
* that is not expressible here; rely on `validatePayload('finding', …)` for it.
|
|
347
|
+
*/
|
|
348
|
+
export interface Finding {
|
|
349
|
+
/** Semver of the finding schema. */
|
|
350
|
+
schema_version: string;
|
|
351
|
+
/** Stable slug. Pattern: `^dfind-[a-z0-9][a-z0-9-]*$`. */
|
|
352
|
+
finding_id: string;
|
|
353
|
+
/** Schema minLength: 10, maxLength: 200. */
|
|
354
|
+
title: string;
|
|
355
|
+
status: FindingStatus;
|
|
356
|
+
/** Full org/repo. Pattern: `^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$`. */
|
|
357
|
+
repo: string;
|
|
358
|
+
product_surface: ProductSurface;
|
|
359
|
+
execution_mode?: ExecutionMode;
|
|
360
|
+
journey_stage: JourneyStage;
|
|
361
|
+
issue_kind: IssueKind;
|
|
362
|
+
root_cause_kind: RootCauseKind;
|
|
363
|
+
remediation_kind: RemediationKind;
|
|
364
|
+
transfer_scope: TransferScope;
|
|
365
|
+
/** Schema minLength: 20, maxLength: 1000. */
|
|
366
|
+
summary: string;
|
|
367
|
+
/** Portable rule derived from this finding. Schema maxLength: 500. */
|
|
368
|
+
doctrine_statement?: string;
|
|
369
|
+
/** Schema maxLength: 2000. */
|
|
370
|
+
notes?: string;
|
|
371
|
+
/** Run IDs of the source records. Schema minItems: 1. */
|
|
372
|
+
source_record_ids: string[];
|
|
373
|
+
/** Scenario IDs relevant to this finding. */
|
|
374
|
+
scenario_ids?: string[];
|
|
375
|
+
/** Structured evidence binding. Schema minItems: 1 — a finding with no evidence is invalid. */
|
|
376
|
+
evidence: FindingEvidence[];
|
|
377
|
+
fix_refs?: FixRef[];
|
|
378
|
+
created_at?: string;
|
|
379
|
+
updated_at?: string;
|
|
380
|
+
derived?: FindingDerived;
|
|
381
|
+
review?: FindingReview;
|
|
382
|
+
lineage?: FindingLineage;
|
|
383
|
+
invalidation?: FindingInvalidation;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Representative valid payloads, one per modelled interface. Exported so the
|
|
387
|
+
* companion vitest can push them through `validatePayload` and assert the JSON
|
|
388
|
+
* schema agrees — the runtime half of the FT-h drift seal. Consumers may also
|
|
389
|
+
* import these as ready-made fixtures.
|
|
390
|
+
*
|
|
391
|
+
* The `as const` example bodies above are `satisfies`-checked against their
|
|
392
|
+
* interfaces; here we widen to the interface types so the exported shape is the
|
|
393
|
+
* interface (not a frozen literal) for downstream reuse.
|
|
394
|
+
*/
|
|
395
|
+
export declare const EXAMPLE_PAYLOADS: {
|
|
396
|
+
submission: Submission;
|
|
397
|
+
scenarioResult: ScenarioResult;
|
|
398
|
+
record: Record;
|
|
399
|
+
finding: Finding;
|
|
400
|
+
};
|
|
401
|
+
//# sourceMappingURL=payload-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-types.d.ts","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAY9E,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9D,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1E,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAExF,6DAA6D;AAC7D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAUrD,gEAAgE;AAChE,MAAM,WAAW,GAAG;IAClB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD,8DAA8D;AAC9D,MAAM,WAAW,MAAM;IACrB,wEAAwE;IACxE,QAAQ,EAAE,cAAc,CAAC;IACzB,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,iEAAiE;AACjE,MAAM,WAAW,MAAM;IACrB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,sEAAsE;AACtE,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,uFAAuF;AACvF,MAAM,WAAW,UAAU;IACzB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,IAAI,EAAE,YAAY,CAAC;IACnB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,cAAc,CAAC;IAChC,cAAc,EAAE,aAAa,CAAC;IAC9B,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IACtB,4CAA4C;IAC5C,gBAAgB,EAAE,cAAc,EAAE,CAAC;IACnC,sCAAsC;IACtC,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,6BAA6B,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,iIAAiI;IACjI,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2HAA2H;IAC3H,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,sIAAsI;IACtI,oBAAoB,EAAE,OAAO,CAAC;IAC9B,wDAAwD;IACxD,YAAY,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,sBAAsB,CAAC,EAAE,qBAAqB,CAAC;CAChD;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,MAAM;IACrB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IACtB,gBAAgB,EAAE,cAAc,EAAE,CAAC;IACnC,eAAe,EAAE,oBAAoB,CAAC;IACtC,YAAY,EAAE,YAAY,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAOD,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AAE/E,wFAAwF;AACxF,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,OAAO,GACP,WAAW,GACX,WAAW,GACX,QAAQ,GACR,SAAS,GACT,UAAU,GACV,aAAa,GACb,cAAc,GACd,SAAS,CAAC;AAEd,qDAAqD;AACrD,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,sBAAsB,GACtB,YAAY,GACZ,iBAAiB,GACjB,uBAAuB,GACvB,wBAAwB,GACxB,wBAAwB,GACxB,yBAAyB,GACzB,iBAAiB,GACjB,0BAA0B,GAC1B,yBAAyB,GACzB,gBAAgB,GAChB,yBAAyB,GACzB,2BAA2B,GAC3B,oBAAoB,GACpB,kBAAkB,GAClB,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,CAAC;AAExB,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,2BAA2B,GAC3B,sBAAsB,GACtB,uBAAuB,GACvB,wBAAwB,GACxB,oBAAoB,GACpB,4BAA4B,GAC5B,aAAa,GACb,aAAa,GACb,mBAAmB,GACnB,0BAA0B,GAC1B,yBAAyB,GACzB,wBAAwB,CAAC;AAE7B,gEAAgE;AAChE,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,iBAAiB,GACjB,oBAAoB,GACpB,YAAY,GACZ,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,6BAA6B,GAC7B,iBAAiB,GACjB,cAAc,GACd,aAAa,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,YAAY,GACZ,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,UAAU,CAAC;AAEf,iFAAiF;AACjF,MAAM,MAAM,mBAAmB,GAC3B,QAAQ,GACR,iBAAiB,GACjB,UAAU,GACV,QAAQ,GACR,UAAU,GACV,KAAK,GACL,WAAW,CAAC;AAEhB,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,mBAAmB,CAAC;IACnC,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4DAA4D;AAC5D,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,IAAI,GACJ,KAAK,GACL,eAAe,GACf,iBAAiB,GACjB,iBAAiB,CAAC;AAEtB,gEAAgE;AAChE,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,UAAU,CAAC;IACrB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,sFAAsF;AACtF,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,WAAW,CAAC;AAEhB,gEAAgE;AAChE,MAAM,MAAM,YAAY,GACpB,uBAAuB,GACvB,WAAW,GACX,sBAAsB,GACtB,cAAc,GACd,OAAO,GACP,sBAAsB,GACtB,uBAAuB,CAAC;AAE5B,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAED,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,iHAAiH;AACjH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,cAAc,CAAC;IAChC,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,aAAa,EAAE,YAAY,CAAC;IAC5B,UAAU,EAAE,SAAS,CAAC;IACtB,eAAe,EAAE,aAAa,CAAC;IAC/B,gBAAgB,EAAE,eAAe,CAAC;IAClC,cAAc,EAAE,aAAa,CAAC;IAC9B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,+FAA+F;IAC/F,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAsHD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAMlB,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-authored TypeScript interfaces for the contract payload shapes.
|
|
3
|
+
*
|
|
4
|
+
* FT-h (Wave, HIGH, consumability). The package exports the JSON-schema
|
|
5
|
+
* OBJECTS, the three full-set enum unions, and `validatePayload`, but no
|
|
6
|
+
* TypeScript interface for the actual payload SHAPES. A TS consumer that
|
|
7
|
+
* builds a submission, reads a persisted record, or constructs a finding got
|
|
8
|
+
* zero compile-time safety on the envelope — `validatePayload` only catches
|
|
9
|
+
* the mistake at runtime, after the bad object already flowed through typed
|
|
10
|
+
* code as `unknown`/`any`.
|
|
11
|
+
*
|
|
12
|
+
* These interfaces give consumers a typed shape to assert against at author
|
|
13
|
+
* time. They are HAND-MAINTAINED to mirror the JSON schemas — there is no
|
|
14
|
+
* codegen step — so each interface and nested type carries a `Mirrors:`
|
|
15
|
+
* pointer to its source schema, and the {@link EXAMPLE_PAYLOADS} consts at the
|
|
16
|
+
* bottom are `satisfies`-checked so `tsc --build` (which CI runs via
|
|
17
|
+
* `npm run verify` → `npm run build`) goes RED the moment an interface drifts
|
|
18
|
+
* from a representative payload. The companion vitest
|
|
19
|
+
* (`test/payload-types.test.ts`) closes the other half of the loop: it pushes
|
|
20
|
+
* those same examples through `validatePayload` and asserts the JSON schema
|
|
21
|
+
* AGREES they are valid. Interface drift in EITHER direction is caught.
|
|
22
|
+
*
|
|
23
|
+
* Reused enum unions: enum-typed fields reference the exported
|
|
24
|
+
* {@link ProductSurface} / {@link ExecutionMode} / {@link EvidenceKind} unions
|
|
25
|
+
* rather than re-typing the literals, so those fields stay sealed to the same
|
|
26
|
+
* single source the cross-contract enum seal enforces on the JSON side.
|
|
27
|
+
*
|
|
28
|
+
* SCOPE — the four payloads FT-h names: {@link Submission},
|
|
29
|
+
* {@link ScenarioResult}, {@link Record}, {@link Finding}. The other four
|
|
30
|
+
* contract schemas (pattern, recommendation, doctrine, policy) are out of
|
|
31
|
+
* scope for this slice and intentionally not modelled here; add them the same
|
|
32
|
+
* way (interface + `Mirrors:` pointer + a `satisfies` example) when a consumer
|
|
33
|
+
* needs them.
|
|
34
|
+
*/
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Representative example payloads — the load-bearing compile-time seal.
|
|
37
|
+
//
|
|
38
|
+
// Each const is `satisfies`-checked against its interface. `tsc --build` (run
|
|
39
|
+
// by CI via `npm run verify` → `npm run build`) compiles this `src/` file, so
|
|
40
|
+
// any field that an interface declares but a representative payload cannot fill
|
|
41
|
+
// — or any interface field that drifts in type from the JSON schema's intent —
|
|
42
|
+
// turns the build RED here, at author time, not at a downstream consumer.
|
|
43
|
+
//
|
|
44
|
+
// `satisfies` (not a type annotation) keeps each const's literal type narrow
|
|
45
|
+
// AND asserts assignability to the interface, so an EXTRA property that the
|
|
46
|
+
// interface forbids is also a compile error. The companion vitest pushes these
|
|
47
|
+
// same values through `validatePayload` so the JSON schema independently agrees
|
|
48
|
+
// they are valid — drift on either side is caught.
|
|
49
|
+
//
|
|
50
|
+
// Values mirror the representative payloads already proven valid in
|
|
51
|
+
// test/validate.test.ts, so they share that file's known-good provenance.
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
const EXAMPLE_SUBMISSION = {
|
|
54
|
+
schema_version: '1.0.0',
|
|
55
|
+
run_id: 'run-01H8Y4ZC9XJWQ5N6',
|
|
56
|
+
repo: 'dogfood-lab/testing-os',
|
|
57
|
+
ref: { commit_sha: 'a'.repeat(40), branch: 'main' },
|
|
58
|
+
source: {
|
|
59
|
+
provider: 'github',
|
|
60
|
+
workflow: 'dogfood.yml',
|
|
61
|
+
provider_run_id: '12345',
|
|
62
|
+
run_url: 'https://github.com/dogfood-lab/testing-os/actions/runs/12345',
|
|
63
|
+
},
|
|
64
|
+
timing: {
|
|
65
|
+
started_at: '2026-04-26T18:00:00Z',
|
|
66
|
+
finished_at: '2026-04-26T18:05:00Z',
|
|
67
|
+
},
|
|
68
|
+
scenario_results: [
|
|
69
|
+
{
|
|
70
|
+
scenario_id: 'cli-resolve-and-list',
|
|
71
|
+
product_surface: 'cli',
|
|
72
|
+
execution_mode: 'bot',
|
|
73
|
+
verdict: 'pass',
|
|
74
|
+
step_results: [{ step_id: 'install', status: 'pass' }],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
overall_verdict: 'pass',
|
|
78
|
+
};
|
|
79
|
+
const EXAMPLE_SCENARIO_RESULT = {
|
|
80
|
+
scenario_id: 'cli-resolve-and-list',
|
|
81
|
+
scenario_name: 'Resolve loadout and list its packages',
|
|
82
|
+
scenario_version: '1.0.0',
|
|
83
|
+
product_surface: 'cli',
|
|
84
|
+
execution_mode: 'mixed',
|
|
85
|
+
attested_by: 'human-attester-01',
|
|
86
|
+
verdict: 'partial',
|
|
87
|
+
step_results: [
|
|
88
|
+
{ step_id: 'install', status: 'pass' },
|
|
89
|
+
{ step_id: 'resolve', status: 'partial', notes: 'slow but completed' },
|
|
90
|
+
],
|
|
91
|
+
evidence: [
|
|
92
|
+
{ kind: 'log', url: 'https://example.com/run.log' },
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
const EXAMPLE_RECORD = {
|
|
96
|
+
schema_version: '1.0.0',
|
|
97
|
+
policy_version: '1.0.0',
|
|
98
|
+
run_id: 'run-01H8Y4ZC9XJWQ5N6',
|
|
99
|
+
repo: 'dogfood-lab/testing-os',
|
|
100
|
+
ref: { commit_sha: 'b'.repeat(40) },
|
|
101
|
+
source: {
|
|
102
|
+
provider: 'github',
|
|
103
|
+
workflow: 'dogfood.yml',
|
|
104
|
+
provider_run_id: '12345',
|
|
105
|
+
run_url: 'https://github.com/dogfood-lab/testing-os/actions/runs/12345',
|
|
106
|
+
},
|
|
107
|
+
timing: {
|
|
108
|
+
started_at: '2026-04-26T18:00:00Z',
|
|
109
|
+
finished_at: '2026-04-26T18:05:00Z',
|
|
110
|
+
},
|
|
111
|
+
scenario_results: [
|
|
112
|
+
{
|
|
113
|
+
scenario_id: 'cli-resolve-and-list',
|
|
114
|
+
product_surface: 'cli',
|
|
115
|
+
execution_mode: 'bot',
|
|
116
|
+
verdict: 'pass',
|
|
117
|
+
step_results: [{ step_id: 'install', status: 'pass' }],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
overall_verdict: { proposed: 'pass', verified: 'pass' },
|
|
121
|
+
verification: {
|
|
122
|
+
status: 'accepted',
|
|
123
|
+
verified_at: '2026-04-26T18:06:00Z',
|
|
124
|
+
provenance_confirmed: true,
|
|
125
|
+
schema_valid: true,
|
|
126
|
+
policy_valid: true,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const EXAMPLE_FINDING = {
|
|
130
|
+
schema_version: '1.0.0',
|
|
131
|
+
finding_id: 'dfind-testing-os-schemas-payload-types',
|
|
132
|
+
title: 'Schemas package shipped no payload interfaces',
|
|
133
|
+
status: 'accepted',
|
|
134
|
+
repo: 'dogfood-lab/testing-os',
|
|
135
|
+
product_surface: 'npm-package',
|
|
136
|
+
journey_stage: 'verification',
|
|
137
|
+
issue_kind: 'schema_mismatch',
|
|
138
|
+
root_cause_kind: 'tooling_gap',
|
|
139
|
+
remediation_kind: 'schema_fix',
|
|
140
|
+
transfer_scope: 'org_wide',
|
|
141
|
+
summary: 'TS consumers of @dogfood-lab/schemas got no compile-time safety on the payload envelope; only validatePayload caught shape errors, at runtime.',
|
|
142
|
+
source_record_ids: ['testing-os-fth-001'],
|
|
143
|
+
evidence: [{ evidence_kind: 'doc', doc_ref: 'packages/schemas/src/payload-types.ts' }],
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Representative valid payloads, one per modelled interface. Exported so the
|
|
147
|
+
* companion vitest can push them through `validatePayload` and assert the JSON
|
|
148
|
+
* schema agrees — the runtime half of the FT-h drift seal. Consumers may also
|
|
149
|
+
* import these as ready-made fixtures.
|
|
150
|
+
*
|
|
151
|
+
* The `as const` example bodies above are `satisfies`-checked against their
|
|
152
|
+
* interfaces; here we widen to the interface types so the exported shape is the
|
|
153
|
+
* interface (not a frozen literal) for downstream reuse.
|
|
154
|
+
*/
|
|
155
|
+
export const EXAMPLE_PAYLOADS = {
|
|
156
|
+
submission: EXAMPLE_SUBMISSION,
|
|
157
|
+
scenarioResult: EXAMPLE_SCENARIO_RESULT,
|
|
158
|
+
record: EXAMPLE_RECORD,
|
|
159
|
+
finding: EXAMPLE_FINDING,
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=payload-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-types.js","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dogfood-lab/schemas",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "JSON schemas for the testing-os contract spine — record, finding, pattern, recommendation, doctrine, policy, scenario, submission.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@dogfood-lab/dogfood-swarm": "*",
|
|
37
37
|
"@types/node": "^25.3.5",
|
|
38
|
-
"vitest": "^4.1.
|
|
38
|
+
"vitest": "^4.1.9"
|
|
39
39
|
},
|
|
40
40
|
"author": "mcp-tool-shop",
|
|
41
41
|
"license": "MIT",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"run_id": {
|
|
27
27
|
"type": "string",
|
|
28
28
|
"minLength": 1,
|
|
29
|
-
"
|
|
29
|
+
"pattern": "^[A-Za-z0-9_-]+$",
|
|
30
|
+
"description": "Unique dogfood run identifier. ULID recommended for sortability. Charset is constrained because run_id becomes a filesystem path segment in the persisted record path; this mirrors the persist-time guard."
|
|
30
31
|
},
|
|
31
32
|
|
|
32
33
|
"repo": {
|
|
@@ -59,16 +60,16 @@
|
|
|
59
60
|
"properties": {
|
|
60
61
|
"provider": {
|
|
61
62
|
"type": "string",
|
|
62
|
-
"enum": ["github"],
|
|
63
|
-
"description": "SCM provider. GitHub-
|
|
63
|
+
"enum": ["github", "gitlab"],
|
|
64
|
+
"description": "SCM provider that ran the workflow. 'github' (GitHub Actions) or 'gitlab' (GitLab CI). The verifier selects a provider-specific provenance adapter to confirm the run."
|
|
64
65
|
},
|
|
65
66
|
"workflow": {
|
|
66
67
|
"type": "string",
|
|
67
|
-
"description": "Workflow filename that produced this submission."
|
|
68
|
+
"description": "Workflow filename that produced this submission (e.g. a GitHub Actions workflow YAML or '.gitlab-ci.yml')."
|
|
68
69
|
},
|
|
69
70
|
"provider_run_id": {
|
|
70
71
|
"type": "string",
|
|
71
|
-
"description": "GitHub Actions run ID (
|
|
72
|
+
"description": "Provider-native run identifier. For 'github' this is the GitHub Actions run ID; for 'gitlab' this is the GitLab pipeline ID (or job ID when run_url points at a job)."
|
|
72
73
|
},
|
|
73
74
|
"attempt": {
|
|
74
75
|
"type": "integer",
|
|
@@ -164,6 +165,11 @@
|
|
|
164
165
|
"type": "string",
|
|
165
166
|
"description": "Required when verdict is blocked. Verifier enforces."
|
|
166
167
|
},
|
|
168
|
+
"tags": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": { "type": "string" },
|
|
171
|
+
"description": "Free-form scenario tags (e.g. 'smoke', 'release', 'wip', 'flaky', 'skip-ci'). Optional. Policy may gate on these via a surface's evidence_requirements.forbidden_tags / required_tags."
|
|
172
|
+
},
|
|
167
173
|
"step_results": {
|
|
168
174
|
"type": "array",
|
|
169
175
|
"minItems": 1,
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"run_id": {
|
|
35
35
|
"type": "string",
|
|
36
36
|
"minLength": 1,
|
|
37
|
-
"
|
|
37
|
+
"pattern": "^[A-Za-z0-9_-]+$",
|
|
38
|
+
"description": "Unique dogfood run identifier. Carried from submission. Charset is constrained because run_id becomes a filesystem path segment in the persisted record path; this mirrors the persist-time guard."
|
|
38
39
|
},
|
|
39
40
|
|
|
40
41
|
"repo": {
|
|
@@ -67,16 +68,16 @@
|
|
|
67
68
|
"properties": {
|
|
68
69
|
"provider": {
|
|
69
70
|
"type": "string",
|
|
70
|
-
"enum": ["github"],
|
|
71
|
-
"description": "SCM provider. GitHub
|
|
71
|
+
"enum": ["github", "gitlab"],
|
|
72
|
+
"description": "SCM provider that ran the workflow. 'github' (GitHub Actions) or 'gitlab' (GitLab CI). Carried verbatim from the submission."
|
|
72
73
|
},
|
|
73
74
|
"workflow": {
|
|
74
75
|
"type": "string",
|
|
75
|
-
"description": "Workflow filename that produced the submission."
|
|
76
|
+
"description": "Workflow filename that produced the submission (e.g. a GitHub Actions workflow YAML or '.gitlab-ci.yml')."
|
|
76
77
|
},
|
|
77
78
|
"provider_run_id": {
|
|
78
79
|
"type": "string",
|
|
79
|
-
"description": "GitHub Actions run ID (
|
|
80
|
+
"description": "Provider-native run identifier. For 'github' this is the GitHub Actions run ID; for 'gitlab' this is the GitLab pipeline ID (or job ID when run_url points at a job)."
|
|
80
81
|
},
|
|
81
82
|
"attempt": {
|
|
82
83
|
"type": "integer",
|
|
@@ -172,6 +173,11 @@
|
|
|
172
173
|
"type": "string",
|
|
173
174
|
"description": "Required when verdict is blocked. Verifier enforces."
|
|
174
175
|
},
|
|
176
|
+
"tags": {
|
|
177
|
+
"type": "array",
|
|
178
|
+
"items": { "type": "string" },
|
|
179
|
+
"description": "Free-form scenario tags (e.g. 'smoke', 'release', 'wip', 'flaky', 'skip-ci'). Carried verbatim from the submission. Policy gates on these via a surface's evidence_requirements.forbidden_tags / required_tags."
|
|
180
|
+
},
|
|
175
181
|
"step_results": {
|
|
176
182
|
"type": "array",
|
|
177
183
|
"minItems": 1,
|
|
@@ -266,7 +272,7 @@
|
|
|
266
272
|
},
|
|
267
273
|
"provenance_confirmed": {
|
|
268
274
|
"type": "boolean",
|
|
269
|
-
"description": "True if
|
|
275
|
+
"description": "True if the provider API (GitHub Actions or GitLab CI, selected by source.provider) confirmed the source run exists and matches the claimed repo, commit, and finished state."
|
|
270
276
|
},
|
|
271
277
|
"schema_valid": {
|
|
272
278
|
"type": "boolean",
|
|
@@ -281,6 +287,11 @@
|
|
|
281
287
|
"items": { "type": "string" },
|
|
282
288
|
"description": "Machine-readable reasons for rejection. Empty if accepted."
|
|
283
289
|
},
|
|
290
|
+
"warnings": {
|
|
291
|
+
"type": "array",
|
|
292
|
+
"items": { "type": "string" },
|
|
293
|
+
"description": "Accepted-with-warning notes from warn-severity policy rules. A populated warnings array does NOT imply rejection — the record was accepted. Optional and backward-compatible: records written before this channel existed have no warnings block. Mirrors the rejection_reasons shape (one machine-readable string per matched warn-rule)."
|
|
294
|
+
},
|
|
284
295
|
"provenance_remediation": {
|
|
285
296
|
"type": "object",
|
|
286
297
|
"properties": {
|
|
@@ -298,6 +309,34 @@
|
|
|
298
309
|
"notes": {
|
|
299
310
|
"type": "string",
|
|
300
311
|
"description": "Freeform summary from the source."
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
"integrity": {
|
|
315
|
+
"type": "object",
|
|
316
|
+
"title": "Integrity Chain Entry",
|
|
317
|
+
"description": "Tamper-evident hash-chain metadata stamped by the persist layer when this record is written. Optional and backward-compatible: records persisted before the integrity chain existed have no integrity block and remain valid. The digest is computed over the record WITH this block removed (you cannot hash the digest into itself), so it is stable regardless of the integrity block's contents.",
|
|
318
|
+
"additionalProperties": false,
|
|
319
|
+
"required": ["submission_digest", "prev_digest", "seq"],
|
|
320
|
+
"properties": {
|
|
321
|
+
"submission_digest": {
|
|
322
|
+
"type": "string",
|
|
323
|
+
"title": "Submission Digest",
|
|
324
|
+
"description": "Lowercase sha256 hex (64 chars) of the canonicalized record with the integrity block removed. Recomputed by the chain verifier to detect tampering.",
|
|
325
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
326
|
+
},
|
|
327
|
+
"prev_digest": {
|
|
328
|
+
"type": "string",
|
|
329
|
+
"title": "Previous Digest",
|
|
330
|
+
"description": "The submission_digest of the previous record in the append-only chain, or 64 zeros (the genesis digest) for the first entry. Links this record to its predecessor.",
|
|
331
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
332
|
+
},
|
|
333
|
+
"seq": {
|
|
334
|
+
"type": "integer",
|
|
335
|
+
"title": "Chain Sequence Number",
|
|
336
|
+
"description": "Monotonic position of this record in the append-only chain, starting at 0 for the genesis entry.",
|
|
337
|
+
"minimum": 0
|
|
338
|
+
}
|
|
339
|
+
}
|
|
301
340
|
}
|
|
302
341
|
}
|
|
303
342
|
}
|
|
@@ -225,7 +225,17 @@
|
|
|
225
225
|
"min_evidence_count": {
|
|
226
226
|
"type": "integer",
|
|
227
227
|
"minimum": 0,
|
|
228
|
-
"description": "Minimum number of evidence items across all scenarios."
|
|
228
|
+
"description": "Minimum number of evidence items required PER scenario. The verifier enforces this against each scenario_result independently, not as a sum across all scenarios."
|
|
229
|
+
},
|
|
230
|
+
"forbidden_tags": {
|
|
231
|
+
"type": "array",
|
|
232
|
+
"items": { "type": "string" },
|
|
233
|
+
"description": "Scenario tags that REJECT a scenario_result on this surface. A scenario_result whose tags include any of these (e.g. 'wip', 'flaky', 'skip-ci') fails policy. Enforced per scenario_result independently."
|
|
234
|
+
},
|
|
235
|
+
"required_tags": {
|
|
236
|
+
"type": "array",
|
|
237
|
+
"items": { "type": "string" },
|
|
238
|
+
"description": "Scenario tags that EVERY scenario_result on this surface must carry. A scenario_result missing any of these (or carrying no tags at all) fails policy. Enforced per scenario_result independently."
|
|
229
239
|
}
|
|
230
240
|
}
|
|
231
241
|
}
|