@humain/humain-code-contracts 0.3.2 → 0.4.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +10 -1
  3. package/dist/flow-admission.d.ts +209 -0
  4. package/dist/flow-admission.d.ts.map +1 -0
  5. package/dist/flow-admission.js +59 -0
  6. package/dist/flow-admission.js.map +1 -0
  7. package/dist/flow-common.d.ts +103 -0
  8. package/dist/flow-common.d.ts.map +1 -0
  9. package/dist/flow-common.js +282 -0
  10. package/dist/flow-common.js.map +1 -0
  11. package/dist/flow-control.d.ts +107 -0
  12. package/dist/flow-control.d.ts.map +1 -0
  13. package/dist/flow-control.js +144 -0
  14. package/dist/flow-control.js.map +1 -0
  15. package/dist/flow-events.d.ts +345 -0
  16. package/dist/flow-events.d.ts.map +1 -0
  17. package/dist/flow-events.js +147 -0
  18. package/dist/flow-events.js.map +1 -0
  19. package/dist/flow-profile.d.ts +200 -0
  20. package/dist/flow-profile.d.ts.map +1 -0
  21. package/dist/flow-profile.js +89 -0
  22. package/dist/flow-profile.js.map +1 -0
  23. package/dist/flow-sizing.d.ts +30 -0
  24. package/dist/flow-sizing.d.ts.map +1 -0
  25. package/dist/flow-sizing.js +568 -0
  26. package/dist/flow-sizing.js.map +1 -0
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/rpc.d.ts +27 -2
  32. package/dist/rpc.d.ts.map +1 -1
  33. package/dist/rpc.js +283 -18
  34. package/dist/rpc.js.map +1 -1
  35. package/dist/trace-artifact.d.ts +1 -1
  36. package/dist/trace-artifact.d.ts.map +1 -1
  37. package/dist/trace-artifact.js +3 -1
  38. package/dist/trace-artifact.js.map +1 -1
  39. package/dist/trace-http.d.ts.map +1 -1
  40. package/dist/trace-http.js +3 -0
  41. package/dist/trace-http.js.map +1 -1
  42. package/dist/trace-payload.d.ts +25 -1
  43. package/dist/trace-payload.d.ts.map +1 -1
  44. package/dist/trace-payload.js +2 -0
  45. package/dist/trace-payload.js.map +1 -1
  46. package/dist/trace-records.d.ts +985 -0
  47. package/dist/trace-records.d.ts.map +1 -0
  48. package/dist/trace-records.js +535 -0
  49. package/dist/trace-records.js.map +1 -0
  50. package/dist/trace.d.ts +1 -0
  51. package/dist/trace.d.ts.map +1 -1
  52. package/dist/trace.js +1 -0
  53. package/dist/trace.js.map +1 -1
  54. package/package.json +29 -5
package/CHANGELOG.md CHANGED
@@ -1,6 +1,30 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [0.4.0] - 2026-10-09
4
+
5
+ ### Added
6
+
7
+ - Add the agent activity trace contracts (`./trace`): packed trace records, batch and control schemas, constant-diagnostic validation of hostile input, and artifact descriptors.
8
+ - Add usage and legal-hold trace records, with checks for usage supersession and legal-hold precedence (0.3.3).
9
+ - Add the public `./flow-common` subpath exporting `FLOW_ID_PATTERN`, `FLOW_DIGEST_PATTERN`, `FLOW_MODEL_ID_PATTERN`, `FlowContractError`, `FlowModelRef`/`FlowModelRefSchema` and `FlowProfileRefV1`/`FlowProfileRefSchema` (also re-exported from the package root).
10
+ - Add `dh.usage-response/1`, `dh.usage-search-page/1` and `dh.usage-correction/1`
11
+ for submission-owned usage: failed-attempt usage is retained and summed,
12
+ inclusive Flow aggregates contribute zero, unknown usage or price stays explicit
13
+ unknown, and corrections append a record that names the record it supersedes.
14
+ - Add `dh.generation-delete-request/1`, `dh.generation-deletion/1`,
15
+ `dh.legal-hold-request/1`, `dh.legal-hold/1` and
16
+ `dh.legal-hold-release-request/1`, with `assertDhHoldPrecedence` and
17
+ `assertDhHoldPlacementAllowed`: an active legal hold takes precedence over
18
+ deletion.
19
+ - Add decisions D18 and D19 to the trace decision record, the `dh-records-v1`
20
+ conformance vectors and 8 schema IDs to the implemented registry (53 total).
21
+
22
+ ### Changed
23
+
24
+ - Origin contractVersion stays 1. Existing `/2` DTOs, `DH_ROUTES` and
25
+ `dh.batch/1-proposal` are unchanged.
26
+ - Flow `ModelRef.model` accepts provider-qualified ids (`anthropic/claude-sonnet`: lowercase, at most one `/`, at most 128 characters). `provider` keeps the plain id pattern.
27
+ - Version `0.4.0`: the Flow contract line, built on 0.3.3. It keeps every 0.3.3 export, record and subpath (including the frozen `./trace` DTOs) unchanged and adds only the `./flow-*` subpaths and additive RPC Flow types.
4
28
 
5
29
  ## [0.3.1] - 2026-10-01
6
30
 
package/README.md CHANGED
@@ -31,10 +31,19 @@ use `/2`. Parser success is not authentication, registry admission or durable re
31
31
  Callers supply authenticated ownership and committed amendment context for retry
32
32
  eligibility; missing authority cannot resolve an unknown terminal.
33
33
 
34
- Package version `0.3.2` records the disabled-by-default C0 technical
34
+ Package version `0.3.3` records the disabled-by-default C0 technical
35
35
  resolution, not production approval. Batch ingress remains exclusively
36
36
  `dh.batch/1-proposal` (`resolved-synthetic-local`); origin contractVersion stays 1.
37
37
 
38
+ Usage and records policy (0.3.3, additions only): `dh.usage-response/1`,
39
+ `dh.usage-search-page/1` and the append-only `dh.usage-correction/1` expose
40
+ submission-owned usage. Failed attempts are summed, inclusive Flow aggregates add
41
+ zero, and unknown usage or price is an explicit unknown, never zero.
42
+ `dh.generation-delete-request/1`, `dh.generation-deletion/1`,
43
+ `dh.legal-hold-request/1`, `dh.legal-hold/1` and
44
+ `dh.legal-hold-release-request/1` cover generation delete and legal holds; an
45
+ active hold always wins over deletion. See decisions D18 and D19.
46
+
38
47
  Read pages and complete cursor bindings use `/2`. A `dh.snapshot-cutoff/1`
39
48
  committed receipt ordinal fixes the snapshot; captureCutoff is display time only.
40
49
  Bindings include the immutable generation root (or project mapping for lists),
@@ -0,0 +1,209 @@
1
+ import { type Static, Type } from "typebox";
2
+ import { type FlowDigestHasher } from "./flow-common.ts";
3
+ export declare const FlowRunAdmissionV1Schema: Type.TObject<{
4
+ readonly schema: Type.TLiteral<"humain-flow-admission">;
5
+ readonly schemaVersion: Type.TLiteral<1>;
6
+ readonly runId: Type.TString;
7
+ readonly surface: Type.TUnion<[Type.TLiteral<"cli">, Type.TLiteral<"web">]>;
8
+ readonly tenantId: Type.TOptional<Type.TString>;
9
+ readonly projectId: Type.TOptional<Type.TString>;
10
+ readonly mode: Type.TUnion<[Type.TLiteral<"auto">, Type.TLiteral<"direct">]>;
11
+ readonly profile: Type.TObject<{
12
+ readonly schema: Type.TLiteral<"humain-flow-profile">;
13
+ readonly schemaVersion: Type.TLiteral<1>;
14
+ readonly id: Type.TString;
15
+ readonly version: Type.TInteger;
16
+ readonly digest: Type.TString;
17
+ readonly kind: Type.TUnion<[Type.TLiteral<"direct">, Type.TLiteral<"flow">]>;
18
+ readonly label: Type.TString;
19
+ readonly description: Type.TOptional<Type.TString>;
20
+ readonly direct: Type.TOptional<Type.TObject<{
21
+ readonly model: Type.TObject<{
22
+ readonly provider: Type.TString;
23
+ readonly model: Type.TString;
24
+ }>;
25
+ readonly fallbacks: Type.TArray<Type.TObject<{
26
+ readonly provider: Type.TString;
27
+ readonly model: Type.TString;
28
+ }>>;
29
+ }>>;
30
+ readonly roles: Type.TOptional<Type.TObject<{
31
+ readonly scout: Type.TOptional<Type.TObject<{
32
+ readonly primary: Type.TObject<{
33
+ readonly provider: Type.TString;
34
+ readonly model: Type.TString;
35
+ }>;
36
+ readonly backups: Type.TArray<Type.TObject<{
37
+ readonly provider: Type.TString;
38
+ readonly model: Type.TString;
39
+ }>>;
40
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
41
+ }>>;
42
+ readonly worker: Type.TOptional<Type.TObject<{
43
+ readonly primary: Type.TObject<{
44
+ readonly provider: Type.TString;
45
+ readonly model: Type.TString;
46
+ }>;
47
+ readonly backups: Type.TArray<Type.TObject<{
48
+ readonly provider: Type.TString;
49
+ readonly model: Type.TString;
50
+ }>>;
51
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
52
+ }>>;
53
+ readonly implementer: Type.TOptional<Type.TObject<{
54
+ readonly primary: Type.TObject<{
55
+ readonly provider: Type.TString;
56
+ readonly model: Type.TString;
57
+ }>;
58
+ readonly backups: Type.TArray<Type.TObject<{
59
+ readonly provider: Type.TString;
60
+ readonly model: Type.TString;
61
+ }>>;
62
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
63
+ }>>;
64
+ readonly lead: Type.TOptional<Type.TObject<{
65
+ readonly primary: Type.TObject<{
66
+ readonly provider: Type.TString;
67
+ readonly model: Type.TString;
68
+ }>;
69
+ readonly backups: Type.TArray<Type.TObject<{
70
+ readonly provider: Type.TString;
71
+ readonly model: Type.TString;
72
+ }>>;
73
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
74
+ }>>;
75
+ readonly lead_large: Type.TOptional<Type.TObject<{
76
+ readonly primary: Type.TObject<{
77
+ readonly provider: Type.TString;
78
+ readonly model: Type.TString;
79
+ }>;
80
+ readonly backups: Type.TArray<Type.TObject<{
81
+ readonly provider: Type.TString;
82
+ readonly model: Type.TString;
83
+ }>>;
84
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
85
+ }>>;
86
+ readonly architect: Type.TOptional<Type.TObject<{
87
+ readonly primary: Type.TObject<{
88
+ readonly provider: Type.TString;
89
+ readonly model: Type.TString;
90
+ }>;
91
+ readonly backups: Type.TArray<Type.TObject<{
92
+ readonly provider: Type.TString;
93
+ readonly model: Type.TString;
94
+ }>>;
95
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
96
+ }>>;
97
+ readonly reviewer: Type.TOptional<Type.TObject<{
98
+ readonly primary: Type.TObject<{
99
+ readonly provider: Type.TString;
100
+ readonly model: Type.TString;
101
+ }>;
102
+ readonly backups: Type.TArray<Type.TObject<{
103
+ readonly provider: Type.TString;
104
+ readonly model: Type.TString;
105
+ }>>;
106
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
107
+ }>>;
108
+ readonly security_reviewer: Type.TOptional<Type.TObject<{
109
+ readonly primary: Type.TObject<{
110
+ readonly provider: Type.TString;
111
+ readonly model: Type.TString;
112
+ }>;
113
+ readonly backups: Type.TArray<Type.TObject<{
114
+ readonly provider: Type.TString;
115
+ readonly model: Type.TString;
116
+ }>>;
117
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
118
+ }>>;
119
+ readonly qa: Type.TOptional<Type.TObject<{
120
+ readonly primary: Type.TObject<{
121
+ readonly provider: Type.TString;
122
+ readonly model: Type.TString;
123
+ }>;
124
+ readonly backups: Type.TArray<Type.TObject<{
125
+ readonly provider: Type.TString;
126
+ readonly model: Type.TString;
127
+ }>>;
128
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
129
+ }>>;
130
+ readonly triage: Type.TOptional<Type.TObject<{
131
+ readonly primary: Type.TObject<{
132
+ readonly provider: Type.TString;
133
+ readonly model: Type.TString;
134
+ }>;
135
+ readonly backups: Type.TArray<Type.TObject<{
136
+ readonly provider: Type.TString;
137
+ readonly model: Type.TString;
138
+ }>>;
139
+ readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
140
+ }>>;
141
+ }>>;
142
+ readonly sizing: Type.TOptional<Type.TObject<{
143
+ readonly classifierPolicyId: Type.TString;
144
+ readonly thresholds: Type.TObject<{
145
+ readonly mediumAt: Type.TNumber;
146
+ readonly largeAt: Type.TNumber;
147
+ }>;
148
+ readonly triageRole: Type.TLiteral<"triage">;
149
+ readonly maxEscalations: Type.TUnion<[Type.TLiteral<0>, Type.TLiteral<1>]>;
150
+ }>>;
151
+ readonly limits: Type.TObject<{
152
+ readonly maxAgents: Type.TInteger;
153
+ readonly maxConcurrent: Type.TInteger;
154
+ readonly maxDepth: Type.TInteger;
155
+ readonly maxRetries: Type.TInteger;
156
+ readonly inactivityMs: Type.TInteger;
157
+ readonly ciWaitMs: Type.TInteger;
158
+ }>;
159
+ readonly spend: Type.TObject<{
160
+ readonly runCapMicrousd: Type.TInteger;
161
+ readonly warnAtPct: Type.TInteger;
162
+ readonly perRoleCapMicrousd: Type.TOptional<Type.TObject<{
163
+ readonly scout: Type.TOptional<Type.TInteger>;
164
+ readonly worker: Type.TOptional<Type.TInteger>;
165
+ readonly implementer: Type.TOptional<Type.TInteger>;
166
+ readonly lead: Type.TOptional<Type.TInteger>;
167
+ readonly lead_large: Type.TOptional<Type.TInteger>;
168
+ readonly architect: Type.TOptional<Type.TInteger>;
169
+ readonly reviewer: Type.TOptional<Type.TInteger>;
170
+ readonly security_reviewer: Type.TOptional<Type.TInteger>;
171
+ readonly qa: Type.TOptional<Type.TInteger>;
172
+ readonly triage: Type.TOptional<Type.TInteger>;
173
+ }>>;
174
+ }>;
175
+ readonly providers: Type.TOptional<Type.TObject<{
176
+ readonly preference: Type.TArray<Type.TString>;
177
+ }>>;
178
+ readonly approval: Type.TOptional<Type.TObject<{
179
+ readonly approvedBy: Type.TString;
180
+ readonly approvedAt: Type.TRefine<Type.TString>;
181
+ }>>;
182
+ readonly builtIn: Type.TOptional<Type.TLiteral<true>>;
183
+ }>;
184
+ readonly sizeOverride: Type.TOptional<Type.TUnion<[Type.TLiteral<"small">, Type.TLiteral<"medium">, Type.TLiteral<"large">]>>;
185
+ readonly directModel: Type.TOptional<Type.TObject<{
186
+ readonly provider: Type.TString;
187
+ readonly model: Type.TString;
188
+ }>>;
189
+ readonly spendCapMicrousd: Type.TInteger;
190
+ readonly inputs: Type.TArray<Type.TObject<{
191
+ readonly kind: Type.TUnion<[Type.TLiteral<"plan">, Type.TLiteral<"sketch">]>;
192
+ readonly ref: Type.TString;
193
+ readonly sha256: Type.TString;
194
+ readonly path: Type.TString;
195
+ }>>;
196
+ readonly issuedAt: Type.TRefine<Type.TString>;
197
+ readonly admissionDigest: Type.TString;
198
+ }>;
199
+ export type FlowRunAdmissionV1 = Static<typeof FlowRunAdmissionV1Schema>;
200
+ /** Canonical text hashed (sha256 hex) to produce `admissionDigest`: the document without `admissionDigest`. */
201
+ export declare function flowAdmissionDigestInput(doc: FlowRunAdmissionV1): string;
202
+ /**
203
+ * SHAPE ONLY: validates structure and the embedded profile's cross-field rules but does NOT verify
204
+ * `admissionDigest` or the embedded profile digest. Prefer {@link parseFlowRunAdmissionV1}.
205
+ */
206
+ export declare function parseFlowRunAdmissionV1Shape(input: unknown): FlowRunAdmissionV1;
207
+ /** Shape validation plus verification of the embedded profile digest and `admissionDigest` (integrity, not authentication). */
208
+ export declare function parseFlowRunAdmissionV1(input: unknown, hasher: FlowDigestHasher): FlowRunAdmissionV1;
209
+ //# sourceMappingURL=flow-admission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-admission.d.ts","sourceRoot":"","sources":["../src/flow-admission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAIN,KAAK,gBAAgB,EAUrB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAIzE,+GAA+G;AAC/G,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAExE;AAYD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAE/E;AAED,+HAA+H;AAC/H,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,kBAAkB,CASpG"}
@@ -0,0 +1,59 @@
1
+ import { Type } from "typebox";
2
+ import { canonicalWithout, compileFlow, FlowContractError, FlowDigestSchema, FlowIdSchema, FlowMicrousdSchema, FlowModelRefSchema, FlowSizeSchema, FlowTimestampSchema, parseFlowData, StrictObject, verifyFlowDigest, } from "./flow-common.js";
3
+ import { FlowProfileV1Schema, flowProfileDigestInput, parseFlowProfileV1Shape } from "./flow-profile.js";
4
+ export const FlowRunAdmissionV1Schema = StrictObject({
5
+ schema: Type.Literal("humain-flow-admission"),
6
+ schemaVersion: Type.Literal(1),
7
+ runId: FlowIdSchema,
8
+ surface: Type.Union([Type.Literal("cli"), Type.Literal("web")]),
9
+ tenantId: Type.Optional(FlowIdSchema),
10
+ projectId: Type.Optional(FlowIdSchema),
11
+ mode: Type.Union([Type.Literal("auto"), Type.Literal("direct")]),
12
+ profile: FlowProfileV1Schema,
13
+ sizeOverride: Type.Optional(FlowSizeSchema),
14
+ directModel: Type.Optional(FlowModelRefSchema),
15
+ spendCapMicrousd: FlowMicrousdSchema,
16
+ inputs: Type.Array(StrictObject({
17
+ kind: Type.Union([Type.Literal("plan"), Type.Literal("sketch")]),
18
+ ref: FlowIdSchema,
19
+ sha256: FlowDigestSchema,
20
+ path: Type.String({ minLength: 1, maxLength: 1024 }),
21
+ }), { maxItems: 64 }),
22
+ issuedAt: FlowTimestampSchema,
23
+ admissionDigest: FlowDigestSchema,
24
+ });
25
+ const Validator = compileFlow(FlowRunAdmissionV1Schema);
26
+ /** Canonical text hashed (sha256 hex) to produce `admissionDigest`: the document without `admissionDigest`. */
27
+ export function flowAdmissionDigestInput(doc) {
28
+ return canonicalWithout(doc, "admissionDigest");
29
+ }
30
+ function isAdmissionShape(value) {
31
+ if (!Validator.Check(value))
32
+ return false;
33
+ try {
34
+ parseFlowProfileV1Shape(value.profile);
35
+ return true;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * SHAPE ONLY: validates structure and the embedded profile's cross-field rules but does NOT verify
43
+ * `admissionDigest` or the embedded profile digest. Prefer {@link parseFlowRunAdmissionV1}.
44
+ */
45
+ export function parseFlowRunAdmissionV1Shape(input) {
46
+ return parseFlowData("admission_invalid", input, isAdmissionShape);
47
+ }
48
+ /** Shape validation plus verification of the embedded profile digest and `admissionDigest` (integrity, not authentication). */
49
+ export function parseFlowRunAdmissionV1(input, hasher) {
50
+ const admission = parseFlowRunAdmissionV1Shape(input);
51
+ if (!verifyFlowDigest(hasher, flowProfileDigestInput(admission.profile), admission.profile.digest)) {
52
+ throw new FlowContractError("digest_mismatch");
53
+ }
54
+ if (!verifyFlowDigest(hasher, flowAdmissionDigestInput(admission), admission.admissionDigest)) {
55
+ throw new FlowContractError("digest_mismatch");
56
+ }
57
+ return admission;
58
+ }
59
+ //# sourceMappingURL=flow-admission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-admission.js","sourceRoot":"","sources":["../src/flow-admission.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport {\n\tcanonicalWithout,\n\tcompileFlow,\n\tFlowContractError,\n\ttype FlowDigestHasher,\n\tFlowDigestSchema,\n\tFlowIdSchema,\n\tFlowMicrousdSchema,\n\tFlowModelRefSchema,\n\tFlowSizeSchema,\n\tFlowTimestampSchema,\n\tparseFlowData,\n\tStrictObject,\n\tverifyFlowDigest,\n} from \"./flow-common.ts\";\nimport { FlowProfileV1Schema, flowProfileDigestInput, parseFlowProfileV1Shape } from \"./flow-profile.ts\";\n\nexport const FlowRunAdmissionV1Schema = StrictObject({\n\tschema: Type.Literal(\"humain-flow-admission\"),\n\tschemaVersion: Type.Literal(1),\n\trunId: FlowIdSchema,\n\tsurface: Type.Union([Type.Literal(\"cli\"), Type.Literal(\"web\")]),\n\ttenantId: Type.Optional(FlowIdSchema),\n\tprojectId: Type.Optional(FlowIdSchema),\n\tmode: Type.Union([Type.Literal(\"auto\"), Type.Literal(\"direct\")]),\n\tprofile: FlowProfileV1Schema,\n\tsizeOverride: Type.Optional(FlowSizeSchema),\n\tdirectModel: Type.Optional(FlowModelRefSchema),\n\tspendCapMicrousd: FlowMicrousdSchema,\n\tinputs: Type.Array(\n\t\tStrictObject({\n\t\t\tkind: Type.Union([Type.Literal(\"plan\"), Type.Literal(\"sketch\")]),\n\t\t\tref: FlowIdSchema,\n\t\t\tsha256: FlowDigestSchema,\n\t\t\tpath: Type.String({ minLength: 1, maxLength: 1024 }),\n\t\t}),\n\t\t{ maxItems: 64 },\n\t),\n\tissuedAt: FlowTimestampSchema,\n\tadmissionDigest: FlowDigestSchema,\n});\nexport type FlowRunAdmissionV1 = Static<typeof FlowRunAdmissionV1Schema>;\n\nconst Validator = compileFlow(FlowRunAdmissionV1Schema);\n\n/** Canonical text hashed (sha256 hex) to produce `admissionDigest`: the document without `admissionDigest`. */\nexport function flowAdmissionDigestInput(doc: FlowRunAdmissionV1): string {\n\treturn canonicalWithout(doc, \"admissionDigest\");\n}\n\nfunction isAdmissionShape(value: unknown): value is FlowRunAdmissionV1 {\n\tif (!Validator.Check(value)) return false;\n\ttry {\n\t\tparseFlowProfileV1Shape(value.profile);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * SHAPE ONLY: validates structure and the embedded profile's cross-field rules but does NOT verify\n * `admissionDigest` or the embedded profile digest. Prefer {@link parseFlowRunAdmissionV1}.\n */\nexport function parseFlowRunAdmissionV1Shape(input: unknown): FlowRunAdmissionV1 {\n\treturn parseFlowData(\"admission_invalid\", input, isAdmissionShape);\n}\n\n/** Shape validation plus verification of the embedded profile digest and `admissionDigest` (integrity, not authentication). */\nexport function parseFlowRunAdmissionV1(input: unknown, hasher: FlowDigestHasher): FlowRunAdmissionV1 {\n\tconst admission = parseFlowRunAdmissionV1Shape(input);\n\tif (!verifyFlowDigest(hasher, flowProfileDigestInput(admission.profile), admission.profile.digest)) {\n\t\tthrow new FlowContractError(\"digest_mismatch\");\n\t}\n\tif (!verifyFlowDigest(hasher, flowAdmissionDigestInput(admission), admission.admissionDigest)) {\n\t\tthrow new FlowContractError(\"digest_mismatch\");\n\t}\n\treturn admission;\n}\n"]}
@@ -0,0 +1,103 @@
1
+ import { type Static, type TLiteral, type TSchema, type TUnion, Type } from "typebox";
2
+ /**
3
+ * Shared primitives for the `./flow-*` contract subpaths. TypeBox-only and browser-safe: no node:* imports,
4
+ * no hashing (callers inject `sha256Hex`), no free-text string types.
5
+ */
6
+ export declare const FLOW_ID_PATTERN = "^[a-z0-9][a-z0-9_.:-]{0,127}$";
7
+ /** Model ids may be provider-qualified: lowercase, at most one `/`, no empty segment, <= 128 chars in total. */
8
+ export declare const FLOW_MODEL_ID_PATTERN = "^(?=.{1,128}$)[a-z0-9][a-z0-9_.:-]*(?:/[a-z0-9][a-z0-9_.:-]*)?$";
9
+ export declare const FLOW_DIGEST_PATTERN = "^[a-f0-9]{64}$";
10
+ export declare const FLOW_CONTRACT_ERROR_CODES: {
11
+ readonly profile_invalid: "Invalid flow profile";
12
+ readonly admission_invalid: "Invalid flow run admission";
13
+ readonly event_invalid: "Invalid flow event";
14
+ readonly command_invalid: "Invalid flow control command";
15
+ readonly receipt_invalid: "Invalid flow control receipt";
16
+ readonly status_invalid: "Invalid flow status";
17
+ readonly digest_mismatch: "Flow digest mismatch";
18
+ readonly digest_unverifiable: "Flow digest cannot be verified";
19
+ readonly canonical_invalid: "Flow data cannot be canonicalized";
20
+ readonly receipt_conflict: "Flow receipt conflicts with the first receipt";
21
+ };
22
+ export type FlowContractErrorCode = keyof typeof FLOW_CONTRACT_ERROR_CODES;
23
+ /** Messages are constants chosen by contract code from `code`; rejected input is never echoed. */
24
+ export declare class FlowContractError extends Error {
25
+ readonly code: FlowContractErrorCode;
26
+ constructor(code: FlowContractErrorCode);
27
+ }
28
+ /** Union of string literals with a precise Static type (a mapped array would infer `never`). */
29
+ export declare const lit: <const T extends readonly string[]>(...values: T) => TUnion<{ -readonly [K in keyof T]: TLiteral<T[K]>; }>;
30
+ export declare const StrictObject: <const T extends Parameters<typeof Type.Object>[0]>(properties: T) => Type.TObject<T>;
31
+ export declare const FlowIdSchema: Type.TString;
32
+ export declare const FlowDigestSchema: Type.TString;
33
+ export declare const FlowTimestampSchema: Type.TRefine<Type.TString>;
34
+ export declare const FlowMicrousdSchema: Type.TInteger;
35
+ export declare const FlowCountSchema: Type.TInteger;
36
+ export declare const FlowPositiveIntSchema: Type.TInteger;
37
+ export declare const FlowModelRefSchema: Type.TObject<{
38
+ readonly provider: Type.TString;
39
+ readonly model: Type.TString;
40
+ }>;
41
+ export type FlowModelRef = Static<typeof FlowModelRefSchema>;
42
+ export declare const FLOW_ROLES: readonly ["scout", "worker", "implementer", "lead", "lead_large", "architect", "reviewer", "security_reviewer", "qa", "triage"];
43
+ export type FlowRole = (typeof FLOW_ROLES)[number];
44
+ export declare const FlowRoleSchema: TUnion<[TLiteral<"scout">, TLiteral<"worker">, TLiteral<"implementer">, TLiteral<"lead">, TLiteral<"lead_large">, TLiteral<"architect">, TLiteral<"reviewer">, TLiteral<"security_reviewer">, TLiteral<"qa">, TLiteral<"triage">]>;
45
+ /** `Partial<Record<FlowRole, T>>` as a strict object. */
46
+ export declare const partialByRole: <T extends TSchema>(schema: T) => Type.TObject<{
47
+ readonly scout: "~optional" extends keyof T ? T : Type.TOptional<T>;
48
+ readonly worker: "~optional" extends keyof T ? T : Type.TOptional<T>;
49
+ readonly implementer: "~optional" extends keyof T ? T : Type.TOptional<T>;
50
+ readonly lead: "~optional" extends keyof T ? T : Type.TOptional<T>;
51
+ readonly lead_large: "~optional" extends keyof T ? T : Type.TOptional<T>;
52
+ readonly architect: "~optional" extends keyof T ? T : Type.TOptional<T>;
53
+ readonly reviewer: "~optional" extends keyof T ? T : Type.TOptional<T>;
54
+ readonly security_reviewer: "~optional" extends keyof T ? T : Type.TOptional<T>;
55
+ readonly qa: "~optional" extends keyof T ? T : Type.TOptional<T>;
56
+ readonly triage: "~optional" extends keyof T ? T : Type.TOptional<T>;
57
+ }>;
58
+ export declare const FLOW_SIZES: readonly ["small", "medium", "large"];
59
+ export type FlowSize = (typeof FLOW_SIZES)[number];
60
+ export declare const FlowSizeSchema: TUnion<[TLiteral<"small">, TLiteral<"medium">, TLiteral<"large">]>;
61
+ export declare const FLOW_FAILURE_CLASSES: readonly ["provider_error", "rate_limit", "timeout", "check_failed", "review_rejected", "qa_failed", "budget_stop", "cancelled", "crash", "unsafe_scope", "stalled", "config_invalid", "internal"];
62
+ export type FlowFailureClass = (typeof FLOW_FAILURE_CLASSES)[number];
63
+ export declare const FlowFailureClassSchema: TUnion<[TLiteral<"provider_error">, TLiteral<"rate_limit">, TLiteral<"timeout">, TLiteral<"check_failed">, TLiteral<"review_rejected">, TLiteral<"qa_failed">, TLiteral<"budget_stop">, TLiteral<"cancelled">, TLiteral<"crash">, TLiteral<"unsafe_scope">, TLiteral<"stalled">, TLiteral<"config_invalid">, TLiteral<"internal">]>;
64
+ export declare const FlowReasonClassSchema: TUnion<[TUnion<[TLiteral<"provider_error">, TLiteral<"rate_limit">, TLiteral<"timeout">, TLiteral<"check_failed">, TLiteral<"review_rejected">, TLiteral<"qa_failed">, TLiteral<"budget_stop">, TLiteral<"cancelled">, TLiteral<"crash">, TLiteral<"unsafe_scope">, TLiteral<"stalled">, TLiteral<"config_invalid">, TLiteral<"internal">]>, TLiteral<"size_underestimated">]>;
65
+ export type FlowReasonClass = Static<typeof FlowReasonClassSchema>;
66
+ export declare const FlowProfileRefSchema: Type.TObject<{
67
+ readonly id: Type.TString;
68
+ readonly version: Type.TInteger;
69
+ readonly digest: Type.TString;
70
+ }>;
71
+ export type FlowProfileRefV1 = Static<typeof FlowProfileRefSchema>;
72
+ /** Hasher injected by the host; keeps contracts free of node:crypto. Required by every digest-verifying parser. */
73
+ export type FlowDigestHasher = {
74
+ sha256Hex: (text: string) => string;
75
+ };
76
+ /** True when `sha256Hex(text)` equals `expected`. A missing, throwing or non-string hasher is a constant error. */
77
+ export declare function verifyFlowDigest(hasher: FlowDigestHasher, text: string, expected: string): boolean;
78
+ /**
79
+ * Plain-data snapshot of untrusted input: own enumerable data properties only (accessors, symbols, exotic and
80
+ * non-plain objects are rejected), bounded depth/size, finite numbers, well-formed strings. Each property is read
81
+ * exactly once, so the snapshot cannot change after it has been validated.
82
+ */
83
+ export declare function snapshotFlowData(input: unknown): unknown;
84
+ /**
85
+ * Snapshot `input`, validate the snapshot, return the snapshot. Anything thrown while inspecting hostile input
86
+ * (getters, proxy traps, forged FlowContractError objects) is discarded and replaced by a NEW constant `code` error;
87
+ * the thrown value is never read, compared or rethrown. Only our own validation, after the snapshot exists, may throw.
88
+ */
89
+ export declare function parseFlowData<T>(code: FlowContractErrorCode, input: unknown, validate: (snapshot: unknown) => snapshot is T): T;
90
+ /** `snapshotFlowData` whose every failure is a new `FlowContractError(code)`; the thrown value is not inspected. */
91
+ export declare function trySnapshotFlowData(code: FlowContractErrorCode, input: unknown): unknown;
92
+ export declare function compileFlow<T extends TSchema>(schema: T): import("typebox/compile").Validator<{}, T, import("typebox").StaticType<[], "Encode", {}, {}, T>, import("typebox").StaticType<[], "Decode", {}, {}, T>>;
93
+ export declare function modelKey(ref: FlowModelRef): string;
94
+ export declare function hasDuplicateModels(refs: readonly FlowModelRef[]): boolean;
95
+ /**
96
+ * Canonical JSON text (RFC 8785 JCS subset): object keys sorted by UTF-16 code unit, no whitespace, `undefined`
97
+ * properties omitted, numbers as ECMAScript Number toString (`JSON.stringify`; -0 prints 0, 1e21 prints 1e+21).
98
+ * Lone surrogates (keys or strings), non-finite numbers and non-JSON values are rejected with a constant error.
99
+ */
100
+ export declare function canonicalFlowJson(value: unknown): string;
101
+ /** Canonical text of `doc` without the property `omit`. */
102
+ export declare function canonicalWithout(doc: object, omit: string): string;
103
+ //# sourceMappingURL=flow-common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-common.d.ts","sourceRoot":"","sources":["../src/flow-common.ts"],"names":[],"mappings":"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"}