@fourier-labs/harbour-contracts 0.22.0 → 0.26.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/contract-release.json +25 -21
- package/dist/gen-ts/ai-callsite-inventory.d.ts +1 -1
- package/dist/gen-ts/contract-release.d.ts +6 -6
- package/dist/gen-ts/contract-release.js +6 -6
- package/dist/gen-ts/deploy-request.d.ts +10 -0
- package/dist/gen-ts/deployment-status-response.d.ts +14 -0
- package/dist/gen-ts/error-category-registry.d.ts +1 -0
- package/dist/gen-ts/error-category-registry.js +2 -0
- package/dist/gen-ts/index.d.ts +2 -0
- package/dist/gen-ts/index.js +2 -0
- package/dist/gen-ts/security-scan-input.d.ts +37 -0
- package/dist/gen-ts/security-scan-input.js +3 -0
- package/dist/gen-ts/security-verdict.d.ts +99 -0
- package/dist/gen-ts/security-verdict.js +3 -0
- package/dist/gen-ts/transform-report.d.ts +27 -14
- package/gen-ts/ai-callsite-inventory.ts +1 -0
- package/gen-ts/contract-release.ts +6 -6
- package/gen-ts/deploy-request.ts +10 -0
- package/gen-ts/deployment-status-response.ts +14 -0
- package/gen-ts/error-category-registry.ts +2 -0
- package/gen-ts/index.ts +2 -0
- package/gen-ts/security-scan-input.ts +40 -0
- package/gen-ts/security-verdict.ts +102 -0
- package/gen-ts/transform-report.ts +30 -14
- package/package.json +1 -1
- package/schema/ai-callsite-inventory.schema.json +1 -0
- package/schema/deploy-request.schema.json +15 -0
- package/schema/deployment-status-response.schema.json +17 -2
- package/schema/error-category.enum.json +1 -0
- package/schema/security-scan-input.schema.json +52 -0
- package/schema/security-verdict.schema.json +102 -0
- package/schema/transform-report.schema.json +32 -18
package/contract-release.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "harbour.contract-release/1.0",
|
|
3
|
-
"repositoryVersion": "0.
|
|
4
|
-
"publishVersion": "0.
|
|
5
|
-
"publishTag": "v0.
|
|
6
|
-
"schemasDigest": "sha256:
|
|
3
|
+
"repositoryVersion": "0.26.0.0",
|
|
4
|
+
"publishVersion": "0.26.0",
|
|
5
|
+
"publishTag": "v0.26.0",
|
|
6
|
+
"schemasDigest": "sha256:510b57798fd632a4fd34ea7701106b03285c491ab1eddbdef7d1ec0f82d7f70c",
|
|
7
7
|
"aiFixturesDigest": "sha256:5d68828a1364dc63cafbb3c2d3f5c5f6c232d5333e7668a9c79e7652e5144b42",
|
|
8
|
-
"generatedGoDigest": "sha256:
|
|
9
|
-
"generatedTypeScriptDigest": "sha256:
|
|
8
|
+
"generatedGoDigest": "sha256:02a598e4606a1d24bbfdd881e548128ce9b60c090db7ff98dcee5bfe94b74ad3",
|
|
9
|
+
"generatedTypeScriptDigest": "sha256:72865190987cb97215b1db19d46e5c54579f2c01677e5b8e5c735df1d669b74b",
|
|
10
10
|
"generatedExclusions": {
|
|
11
11
|
"gen-go/contract_release.go": "contains the generated aggregate digests (self-reference)",
|
|
12
12
|
"gen-ts/contract-release.ts": "contains the generated aggregate digests (self-reference)"
|
|
13
13
|
},
|
|
14
14
|
"schemas": {
|
|
15
15
|
"schema/ai-budget-ledger-event.schema.json": "sha256:92770bc5358e03a3aae6cd261dad02dfcbbb06a6203566da2c6c7a5e63dd671c",
|
|
16
|
-
"schema/ai-callsite-inventory.schema.json": "sha256:
|
|
16
|
+
"schema/ai-callsite-inventory.schema.json": "sha256:dc607b008336add7ff41b414987a961f89440fb46e1c655bf116a937451c7cf7",
|
|
17
17
|
"schema/ai-classification-stamp.schema.json": "sha256:ad7f01dc8bb9a1cd619fce470227914aa3ef2ad57d34bfeaa0c6ef753aa6781d",
|
|
18
18
|
"schema/ai-composite-policy-digest.schema.json": "sha256:3efccc249327e59f67a37fd954b524ee727a3e28a3c557a46d6ec1f15d69b34e",
|
|
19
19
|
"schema/ai-deployment-gate-decision.schema.json": "sha256:bae1bdf91777b9a78f8da5a29f06b5de7f1e235789cf16b1bb507e85ad0243ff",
|
|
@@ -36,22 +36,24 @@
|
|
|
36
36
|
"schema/data-dependency.schema.json": "sha256:89ba8481ccabc935e7dab5d13871c985839a751ad1586710d8382a15e1f3340c",
|
|
37
37
|
"schema/data-grant.schema.json": "sha256:e640553831ecc1c01cc9a37fe388b84d0ffeaa0d0050e63712b48f65fa437c8a",
|
|
38
38
|
"schema/data-source.schema.json": "sha256:5a809171cc97f5778ca37db300d454098ce1c2d9071d2380550707b049899a75",
|
|
39
|
-
"schema/deploy-request.schema.json": "sha256:
|
|
39
|
+
"schema/deploy-request.schema.json": "sha256:5a1326271f88575719a24f39d14c34959764f6eb8efef71a1f140e30c6c235c7",
|
|
40
40
|
"schema/deploy-response.schema.json": "sha256:09064948abdbba7022738285d802ed44648a16ddc2a5b8c2eeb170ae19a66aeb",
|
|
41
41
|
"schema/deployment-environment.schema.json": "sha256:3f1325d5579b3fc47d02c83b6ac0657108909b1dfb901f68203c9c8b668c2ef4",
|
|
42
42
|
"schema/deployment-source.schema.json": "sha256:256988b1efbfc90bd0e1ae31a2c5d69b20ef1e4471dc24c9f9aa759278270fbe",
|
|
43
43
|
"schema/deployment-status-failure.schema.json": "sha256:1a182e603d22467a4be507a37fd10698f6f3178d314d33eaf5de2c7f687c9412",
|
|
44
44
|
"schema/deployment-status-request.schema.json": "sha256:1f9f87adc947a252b53b61f71ae17f8c1b8fbc1166f31301a043d11ac257dc66",
|
|
45
|
-
"schema/deployment-status-response.schema.json": "sha256:
|
|
45
|
+
"schema/deployment-status-response.schema.json": "sha256:f3e3fb919279095e3f1b35302c549972537bfe9d4f3b305f14b1391f71e66e2c",
|
|
46
46
|
"schema/env-bindings.schema.json": "sha256:ae09bc4ca5508afa698ef854a59153c4c6f99b07017b48cb9b07ce05abad12f2",
|
|
47
|
-
"schema/error-category.enum.json": "sha256:
|
|
47
|
+
"schema/error-category.enum.json": "sha256:693f8ce67d5554358f89b76132024cb8a082216f192d80a66bc4dc64e8983332",
|
|
48
48
|
"schema/error-envelope.schema.json": "sha256:75dccda7dd16fdf8435deda53fc7dbcdc109b65114617a17f11763010c656f90",
|
|
49
49
|
"schema/kvs-routing-entry.schema.json": "sha256:b75f3a5dfa93a428b2764e03222b66b6ef2bed980f8bac8ffac54afdf3526bc5",
|
|
50
50
|
"schema/promotion-request.schema.json": "sha256:560460b57fc639d248fa657a2a1e3d88d27ab9139faf17ee58633b671f8b5072",
|
|
51
51
|
"schema/promotion-response.schema.json": "sha256:4129712d2e29d6ef21d93d4bd0bacfd60ada3f2ee0ade852824e64346b817634",
|
|
52
52
|
"schema/sanitized-binding-evidence.schema.json": "sha256:b03bcc1911c99c69fda50eb656fc3e115f88fe2990c1708fbb5cd3542f4b8bba",
|
|
53
53
|
"schema/secret-reference.schema.json": "sha256:966f7a6d2575b46a4b54804d06dc05c6229ebbcbd9200fe6a6c8d3b4ffb90f9f",
|
|
54
|
-
"schema/
|
|
54
|
+
"schema/security-scan-input.schema.json": "sha256:9f9c9e6131c1abee454320b77e4332e3780c0c63f108f54f75c93194a32ccff7",
|
|
55
|
+
"schema/security-verdict.schema.json": "sha256:ec3c2d5c9df3601aeed0909b36c7f427469c7f0eeb3295c5809b96d09bf3fc26",
|
|
56
|
+
"schema/transform-report.schema.json": "sha256:821755a9d13be24139b168cc11d494c080194eb5a85950dd4878049a59557cea",
|
|
55
57
|
"schema/version-state.schema.json": "sha256:e7c4b2e7b615ebb07f36d0df22ded51b2c9688ef9e9bfe79de1d5cd94de9ae40"
|
|
56
58
|
},
|
|
57
59
|
"aiFixtures": {
|
|
@@ -87,16 +89,16 @@
|
|
|
87
89
|
"gen-go/ai_contracts_test.go": "sha256:17ce967139e39c291ee7ebad3f66cc0495324abc4e56885279f7e5cc74994036",
|
|
88
90
|
"gen-go/ai_gateway_key_token.go": "sha256:859c34383955f21c22589158214df074b74de6907a54bee7c781acfa9dad8679",
|
|
89
91
|
"gen-go/binding_digest_helpers.go": "sha256:50462ba2beb16c7931dfc7e10302c12c90bf8111788991f74f08a718125dfbfb",
|
|
90
|
-
"gen-go/contracts_test.go": "sha256:
|
|
92
|
+
"gen-go/contracts_test.go": "sha256:7c7ee46f2b4277e22b1ee21af9f17d201eb83067c613b049749f932706ed24f8",
|
|
91
93
|
"gen-go/doc.go": "sha256:c17bc2d39ed175ce7105c68305f8ae7152f659eb7cd187ecceee7698eb3a65dd",
|
|
92
|
-
"gen-go/error_category.go": "sha256:
|
|
93
|
-
"gen-go/schema_documents.go": "sha256:
|
|
94
|
-
"gen-go/types.go": "sha256:
|
|
94
|
+
"gen-go/error_category.go": "sha256:a8b64524be3716e62ca6016e56f2332a56fa5e16e42647421e516aa01a7d6806",
|
|
95
|
+
"gen-go/schema_documents.go": "sha256:10fcbf0966bca7d81fc1456afe8744a94d4ebf7d2863b49e6f4f179cbfb69f7e",
|
|
96
|
+
"gen-go/types.go": "sha256:4df0d1c9ba000cad237c3bb37c66ed646b4fc7d0cd41037b49c7264ad4934186",
|
|
95
97
|
"gen-go/version_state.go": "sha256:827f8768359998409b86ea02d9ba1a149981928bae7161e4dc95fe0520ce7410"
|
|
96
98
|
},
|
|
97
99
|
"generatedTypeScript": {
|
|
98
100
|
"gen-ts/ai-budget-ledger-event.ts": "sha256:64448d98a394e6eb103927cd35ce8a33e30176c0d5ee5afcdd8444f8aa051809",
|
|
99
|
-
"gen-ts/ai-callsite-inventory.ts": "sha256:
|
|
101
|
+
"gen-ts/ai-callsite-inventory.ts": "sha256:f6ea0fd19a8cde08b92567255a8fa89bf599bab6dbcf007e484474c3ab28f637",
|
|
100
102
|
"gen-ts/ai-classification-stamp.ts": "sha256:dce78efba03df86a0986a16fd54c52066d322ff515d2463dbc45cafad82ecb44",
|
|
101
103
|
"gen-ts/ai-composite-policy-digest-helper.ts": "sha256:d6c51d0c35599ee4f81d605b71773f4fff41a0bb46499ff0c6185072fedf53ce",
|
|
102
104
|
"gen-ts/ai-composite-policy-digest.ts": "sha256:26b72227ca511d744c0f27fa0c85eb1ba6451ee380e38371e58a810898cfae96",
|
|
@@ -122,25 +124,27 @@
|
|
|
122
124
|
"gen-ts/data-dependency.ts": "sha256:0572c31d7ae9088eccc104eee1a205bf176d1d6dacfaf0f290d666024e284966",
|
|
123
125
|
"gen-ts/data-grant.ts": "sha256:2358579d8aa1e57b01a6f2b0eacce5531e7f21ef226404c9809925365e0d6155",
|
|
124
126
|
"gen-ts/data-source.ts": "sha256:71be83b050468c2ea8c5830d28f1837c2b5929d23b4fdf6661bc5bfe8999904c",
|
|
125
|
-
"gen-ts/deploy-request.ts": "sha256:
|
|
127
|
+
"gen-ts/deploy-request.ts": "sha256:959fbb7c4c055aed7f5f3201612b5e0bb664883220c47019c101532adb1375fc",
|
|
126
128
|
"gen-ts/deploy-response.ts": "sha256:364d9f1acf32e491498237cdd3f402d5f8e102f208db7748034f4ec68c6a6137",
|
|
127
129
|
"gen-ts/deployment-environment.ts": "sha256:bbd6eec3a1631b13a8de6e6b95081696f7be01d0bd2bf1b7a9e3a1db809a727c",
|
|
128
130
|
"gen-ts/deployment-source.ts": "sha256:8ccb55aaa7260eb6d19a00987d6a20a4b514e343564da13f27cd7fee8013500a",
|
|
129
131
|
"gen-ts/deployment-status-failure.ts": "sha256:3ffe268e32240f9da3172b161b8e99e06aa2d21d8c37b30f340506a337c64047",
|
|
130
132
|
"gen-ts/deployment-status-request.ts": "sha256:7ddccd07ab9f6d0821903a291ab35f903bb055727e03a058b99165ec048f6483",
|
|
131
|
-
"gen-ts/deployment-status-response.ts": "sha256:
|
|
133
|
+
"gen-ts/deployment-status-response.ts": "sha256:40ec6a03d8b287465007ff35d6abfbae3541a7beea503e02a2ed5aa391f447c2",
|
|
132
134
|
"gen-ts/env-bindings.ts": "sha256:a167cfe9842352c9fec6412ff0d82bda9c5f5c3a1af541bd5c27a57f54fd0941",
|
|
133
|
-
"gen-ts/error-category-registry.ts": "sha256:
|
|
135
|
+
"gen-ts/error-category-registry.ts": "sha256:280a12aecc8aea8e6e2f2a54d2e968ff7807b522cc0c4036e6e41c065edcf3b7",
|
|
134
136
|
"gen-ts/error-category.ts": "sha256:9bda89180c3b740c9aa8be466216592e8ca9d0d368c274333edf6ea5c45afd8e",
|
|
135
137
|
"gen-ts/error-envelope.ts": "sha256:4457309be794f9d4fc0cf62530cc2d442c007bac9ae84aff66df099cc9e40310",
|
|
136
|
-
"gen-ts/index.ts": "sha256:
|
|
138
|
+
"gen-ts/index.ts": "sha256:bb37bf7838034dcf410562855582ae3bfbf24ee43d506bbc514ad512557016b5",
|
|
137
139
|
"gen-ts/kvs-routing-entry.ts": "sha256:d92e85ee9f257d77850d1d3aac9438e2055f38084ff84a48fcedae239d47d4ca",
|
|
138
140
|
"gen-ts/promotion-request.ts": "sha256:6ef4612172202bca918a6260d40f2a1a8739845c6c0f747dd1ce5e520e081011",
|
|
139
141
|
"gen-ts/promotion-response.ts": "sha256:f1c9cafac96faeb02a443a31786f67714e818f38d90108e7af41958396524d6f",
|
|
140
142
|
"gen-ts/sanitized-binding-digest-helper.ts": "sha256:c47d7fdc20500e2e72c23fe39ecdd610fc397c47fcba51335ebec3c380fe6872",
|
|
141
143
|
"gen-ts/sanitized-binding-evidence.ts": "sha256:4db7e9ed83f563a46e337815a55bbd6433864c41d9ec8e8a80810a16e3095ebb",
|
|
142
144
|
"gen-ts/secret-reference.ts": "sha256:a8b65de72705b6f51f57cd8ca58881483108005b1fa4d19106c3e9cf1fa877e7",
|
|
143
|
-
"gen-ts/
|
|
145
|
+
"gen-ts/security-scan-input.ts": "sha256:5d9bde7394d8b34cca1d36b51ce17bf73cfccd9cfd7cab810f83d4de58f22285",
|
|
146
|
+
"gen-ts/security-verdict.ts": "sha256:fea950cddbd12fe0218e2573c9a29c6748d56612a464559f1e6d688fa97f68c7",
|
|
147
|
+
"gen-ts/transform-report.ts": "sha256:c59e2e3c91c8ef6727a030a0e0763e3b57aa0c80f1873ddcf1a34a3c82cd0f99",
|
|
144
148
|
"gen-ts/version-state-machine.ts": "sha256:4371bc7e2bde86b0447f5242104c576cc160dfd7dae1885acbfb63540f230bdd",
|
|
145
149
|
"gen-ts/version-state.ts": "sha256:a835112930299e7b593a1b8810b7414f6c9e809da2092306c743128170a3b702"
|
|
146
150
|
}
|
|
@@ -29,7 +29,7 @@ export interface AiInventoryCallsite {
|
|
|
29
29
|
sourceFileSha256: AiInventoryDigest;
|
|
30
30
|
line: number;
|
|
31
31
|
language: 'javascript' | 'typescript' | 'python' | 'go' | 'unknown';
|
|
32
|
-
sdk: 'openai' | 'openai-compatible' | 'anthropic' | 'google-genai' | 'mistral' | 'bedrock' | 'cohere' | 'ollama' | 'legacy-gemini' | 'direct-provider-rest' | 'deepgram' | 'unknown';
|
|
32
|
+
sdk: 'openai' | 'openai-compatible' | 'anthropic' | 'google-genai' | 'mistral' | 'bedrock' | 'cohere' | 'ollama' | 'legacy-gemini' | 'external-provider-cli' | 'direct-provider-rest' | 'deepgram' | 'unknown';
|
|
33
33
|
method: string;
|
|
34
34
|
requestedModel?: string;
|
|
35
35
|
strategy: 'deployment_injection' | 'deterministic_adapter' | 'unsupported';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export declare const ContractRepositoryVersion: "0.
|
|
2
|
-
export declare const ContractPublishVersion: "0.
|
|
3
|
-
export declare const ContractPublishTag: "v0.
|
|
4
|
-
export declare const ContractSchemasDigest: "sha256:
|
|
1
|
+
export declare const ContractRepositoryVersion: "0.26.0.0";
|
|
2
|
+
export declare const ContractPublishVersion: "0.26.0";
|
|
3
|
+
export declare const ContractPublishTag: "v0.26.0";
|
|
4
|
+
export declare const ContractSchemasDigest: "sha256:510b57798fd632a4fd34ea7701106b03285c491ab1eddbdef7d1ec0f82d7f70c";
|
|
5
5
|
export declare const ContractAiFixturesDigest: "sha256:5d68828a1364dc63cafbb3c2d3f5c5f6c232d5333e7668a9c79e7652e5144b42";
|
|
6
|
-
export declare const ContractGeneratedGoDigest: "sha256:
|
|
7
|
-
export declare const ContractGeneratedTypeScriptDigest: "sha256:
|
|
6
|
+
export declare const ContractGeneratedGoDigest: "sha256:02a598e4606a1d24bbfdd881e548128ce9b60c090db7ff98dcee5bfe94b74ad3";
|
|
7
|
+
export declare const ContractGeneratedTypeScriptDigest: "sha256:72865190987cb97215b1db19d46e5c54579f2c01677e5b8e5c735df1d669b74b";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
|
-
export const ContractRepositoryVersion = "0.
|
|
4
|
-
export const ContractPublishVersion = "0.
|
|
5
|
-
export const ContractPublishTag = "v0.
|
|
6
|
-
export const ContractSchemasDigest = "sha256:
|
|
3
|
+
export const ContractRepositoryVersion = "0.26.0.0";
|
|
4
|
+
export const ContractPublishVersion = "0.26.0";
|
|
5
|
+
export const ContractPublishTag = "v0.26.0";
|
|
6
|
+
export const ContractSchemasDigest = "sha256:510b57798fd632a4fd34ea7701106b03285c491ab1eddbdef7d1ec0f82d7f70c";
|
|
7
7
|
export const ContractAiFixturesDigest = "sha256:5d68828a1364dc63cafbb3c2d3f5c5f6c232d5333e7668a9c79e7652e5144b42";
|
|
8
|
-
export const ContractGeneratedGoDigest = "sha256:
|
|
9
|
-
export const ContractGeneratedTypeScriptDigest = "sha256:
|
|
8
|
+
export const ContractGeneratedGoDigest = "sha256:02a598e4606a1d24bbfdd881e548128ce9b60c090db7ff98dcee5bfe94b74ad3";
|
|
9
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:72865190987cb97215b1db19d46e5c54579f2c01677e5b8e5c735df1d669b74b";
|
|
@@ -54,6 +54,7 @@ export interface DeployRequest {
|
|
|
54
54
|
* Preview-only. When true, the transformed code is NOT committed back to the source branch (benchmark deploys). Ignored outside preview.
|
|
55
55
|
*/
|
|
56
56
|
benchRun?: boolean;
|
|
57
|
+
transform?: DeployRequestTransform;
|
|
57
58
|
bindingClassification: BindingClassificationSubject;
|
|
58
59
|
}
|
|
59
60
|
export interface DeployRequestSource {
|
|
@@ -75,6 +76,15 @@ export interface DeployRequestEnvironmentBindings {
|
|
|
75
76
|
*/
|
|
76
77
|
bindings: DeployRequestEnvironmentBinding[];
|
|
77
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Optional transformation-engine selection. Absence preserves the existing sequential engine.
|
|
81
|
+
*/
|
|
82
|
+
export interface DeployRequestTransform {
|
|
83
|
+
/**
|
|
84
|
+
* Transformation engine. Omit to preserve the existing sequential default.
|
|
85
|
+
*/
|
|
86
|
+
strategy?: 'sequential' | 'branch_select';
|
|
87
|
+
}
|
|
78
88
|
/**
|
|
79
89
|
* Complete pre-allocation, value-free binding-name classification. DCP verifies its tenant/app/environment/source identity and exact name coverage before minting the versionId.
|
|
80
90
|
*/
|
|
@@ -13,6 +13,10 @@ export interface DeploymentStatusResponse {
|
|
|
13
13
|
commit: string;
|
|
14
14
|
requestedAt: string;
|
|
15
15
|
updatedAt: string;
|
|
16
|
+
/**
|
|
17
|
+
* Transformation engine persisted for this immutable version. Older stored versions are projected as sequential.
|
|
18
|
+
*/
|
|
19
|
+
transformStrategy: 'sequential' | 'branch_select';
|
|
16
20
|
url?: string;
|
|
17
21
|
failure?: StatusFailureProjection;
|
|
18
22
|
/**
|
|
@@ -49,4 +53,14 @@ export interface StatusProgressEvent {
|
|
|
49
53
|
* Short frontend-safe detail. Like the failure projection, it carries no internal identifiers, raw provider errors or secrets.
|
|
50
54
|
*/
|
|
51
55
|
detail?: string;
|
|
56
|
+
strategy?: 'branch_select';
|
|
57
|
+
knowledgeVersion?: string;
|
|
58
|
+
branchId?: string;
|
|
59
|
+
action?: 'continue' | 'widen' | 'kill' | 'unsupported';
|
|
60
|
+
planConfidence?: 'high' | 'medium' | 'low';
|
|
61
|
+
optionCount?: number;
|
|
62
|
+
depth?: number;
|
|
63
|
+
failureCategory?: string;
|
|
64
|
+
remainingMs?: number;
|
|
65
|
+
origin?: 'initial' | 'widen';
|
|
52
66
|
}
|
|
@@ -9,6 +9,7 @@ export declare const ErrorCategories: {
|
|
|
9
9
|
readonly SecretsLeakedInArtifact: "secrets.leaked-in-artifact";
|
|
10
10
|
readonly StorageSqliteMisclassified: "storage.sqlite-misclassified";
|
|
11
11
|
readonly StorageMappingDrift: "storage.mapping-drift";
|
|
12
|
+
readonly StorageUnavailable: "storage.unavailable";
|
|
12
13
|
readonly TransformDeadlineExceeded: "transform.deadline-exceeded";
|
|
13
14
|
readonly TransformValidationFailed: "transform.validation-failed";
|
|
14
15
|
readonly FrontendEnvInlinedUnfixable: "frontend.env-inlined-unfixable";
|
|
@@ -11,6 +11,7 @@ export const ErrorCategories = {
|
|
|
11
11
|
SecretsLeakedInArtifact: "secrets.leaked-in-artifact",
|
|
12
12
|
StorageSqliteMisclassified: "storage.sqlite-misclassified",
|
|
13
13
|
StorageMappingDrift: "storage.mapping-drift",
|
|
14
|
+
StorageUnavailable: "storage.unavailable",
|
|
14
15
|
TransformDeadlineExceeded: "transform.deadline-exceeded",
|
|
15
16
|
TransformValidationFailed: "transform.validation-failed",
|
|
16
17
|
FrontendEnvInlinedUnfixable: "frontend.env-inlined-unfixable",
|
|
@@ -54,6 +55,7 @@ const retryableExact = {
|
|
|
54
55
|
"secrets.leaked-in-artifact": false,
|
|
55
56
|
"storage.sqlite-misclassified": false,
|
|
56
57
|
"storage.mapping-drift": false,
|
|
58
|
+
"storage.unavailable": true,
|
|
57
59
|
"transform.deadline-exceeded": false,
|
|
58
60
|
"transform.validation-failed": true,
|
|
59
61
|
"frontend.env-inlined-unfixable": false,
|
package/dist/gen-ts/index.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export * from './promotion-response.js';
|
|
|
43
43
|
export * from './sanitized-binding-digest-helper.js';
|
|
44
44
|
export * from './sanitized-binding-evidence.js';
|
|
45
45
|
export * from './secret-reference.js';
|
|
46
|
+
export * from './security-scan-input.js';
|
|
47
|
+
export * from './security-verdict.js';
|
|
46
48
|
export * from './transform-report.js';
|
|
47
49
|
export * from './version-state-machine.js';
|
|
48
50
|
export * from './version-state.js';
|
package/dist/gen-ts/index.js
CHANGED
|
@@ -45,6 +45,8 @@ export * from './promotion-response.js';
|
|
|
45
45
|
export * from './sanitized-binding-digest-helper.js';
|
|
46
46
|
export * from './sanitized-binding-evidence.js';
|
|
47
47
|
export * from './secret-reference.js';
|
|
48
|
+
export * from './security-scan-input.js';
|
|
49
|
+
export * from './security-verdict.js';
|
|
48
50
|
export * from './transform-report.js';
|
|
49
51
|
export * from './version-state-machine.js';
|
|
50
52
|
export * from './version-state.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input to the Harbour Security Assurance machine (Security Assurance LLD §2). M1 runs the SOURCE phase only; ARTIFACT is reserved in the enum so the contract is stable through M2. `commit` is the identity being scanned; `org/app/env` locate the snapshot (the control-state table has no commit GSI, so a bare commit is not resolvable); `branch` is caller-supplied provenance.
|
|
3
|
+
*/
|
|
4
|
+
export interface SecurityScanInput {
|
|
5
|
+
/**
|
|
6
|
+
* Scan phase. M1 implements SOURCE only; ARTIFACT is reserved for M2 (image scan against an ECR digest) and is rejected by the machine until then.
|
|
7
|
+
*/
|
|
8
|
+
phase: 'SOURCE' | 'ARTIFACT';
|
|
9
|
+
/**
|
|
10
|
+
* Harbour organization id, e.g. fourier.
|
|
11
|
+
*/
|
|
12
|
+
org: string;
|
|
13
|
+
/**
|
|
14
|
+
* Harbour app id within the org, e.g. focuslist.
|
|
15
|
+
*/
|
|
16
|
+
app: string;
|
|
17
|
+
/**
|
|
18
|
+
* Environment whose ingested snapshots are searched for the commit. M1 deploys preview-only; prod is contract-stable for M3.
|
|
19
|
+
*/
|
|
20
|
+
env: 'preview' | 'prod';
|
|
21
|
+
/**
|
|
22
|
+
* GitHub owner/name of the source repository, e.g. Fourier-Labs-AI/focus-list.
|
|
23
|
+
*/
|
|
24
|
+
repo: string;
|
|
25
|
+
/**
|
|
26
|
+
* Full 40-hex lowercase commit SHA — the identity being scanned.
|
|
27
|
+
*/
|
|
28
|
+
commit: string;
|
|
29
|
+
/**
|
|
30
|
+
* Branch name, supplied authoritatively by the caller in v1 (provenance only — never used for resolution).
|
|
31
|
+
*/
|
|
32
|
+
branch: string;
|
|
33
|
+
/**
|
|
34
|
+
* Data classification of the app. Optional in v1 (decided 2026-08-27): when ABSENT the machine assumes the STANDARD profile and stamps classificationDefaulted: true in the verdict provenance. An invalid value still fails closed — only absence defaults. No classifier exists until M4; until then callers state it or accept the default.
|
|
35
|
+
*/
|
|
36
|
+
classification?: 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED';
|
|
37
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision produced by the Harbour Security Assurance machine (Security Assurance LLD §2). `outcome: BLOCKED` surfaces to callers as the registered non-retryable `gate.security-scan` error category; `reason` is present exactly when BLOCKED. The S3 evidence object named by `evidenceRef` is the full record — in-payload findings may be truncated.
|
|
3
|
+
*/
|
|
4
|
+
export interface SecurityVerdict {
|
|
5
|
+
/**
|
|
6
|
+
* Fail-closed decision: any missing or UNAVAILABLE required evidence is BLOCKED, never PASS.
|
|
7
|
+
*/
|
|
8
|
+
outcome: 'PASS' | 'BLOCKED';
|
|
9
|
+
/**
|
|
10
|
+
* Policy profile the evidence was evaluated against (derived from the input classification; STANDARD when the classification was absent).
|
|
11
|
+
*/
|
|
12
|
+
profile: 'BASELINE' | 'STANDARD' | 'HIGH' | 'CRITICAL';
|
|
13
|
+
/**
|
|
14
|
+
* Human-readable cause, present when outcome is BLOCKED; becomes the Fail-state cause of HarbourSecurityBlocked.
|
|
15
|
+
*/
|
|
16
|
+
reason?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Map of scan-category (e.g. source-secrets, dependency-sca) to its evidence. Kept as an open map so new categories (M2+) are additive, not a schema change.
|
|
19
|
+
*/
|
|
20
|
+
evidence: {
|
|
21
|
+
[k: string]: ScanEvidence;
|
|
22
|
+
};
|
|
23
|
+
evidenceRef: EvidenceRef;
|
|
24
|
+
provenance: Provenance;
|
|
25
|
+
}
|
|
26
|
+
export interface ScanEvidence {
|
|
27
|
+
/**
|
|
28
|
+
* UNAVAILABLE means the tool did not run or did not produce parseable output; policy treats it as blocking for required categories.
|
|
29
|
+
*/
|
|
30
|
+
status: 'PASS' | 'FAIL' | 'UNAVAILABLE';
|
|
31
|
+
/**
|
|
32
|
+
* Normalized, deduplicated findings. May be truncated in-payload; the S3 evidence object is complete.
|
|
33
|
+
*/
|
|
34
|
+
findings: Finding[];
|
|
35
|
+
}
|
|
36
|
+
export interface Finding {
|
|
37
|
+
/**
|
|
38
|
+
* Producing tool, e.g. gitleaks, trivy.
|
|
39
|
+
*/
|
|
40
|
+
tool: string;
|
|
41
|
+
/**
|
|
42
|
+
* Tool-native rule or vulnerability id, e.g. aws-access-key-id, CVE-2024-12345.
|
|
43
|
+
*/
|
|
44
|
+
ruleId: string;
|
|
45
|
+
/**
|
|
46
|
+
* Tool-native severity, normalized upper-case, e.g. CRITICAL, HIGH.
|
|
47
|
+
*/
|
|
48
|
+
severity: string;
|
|
49
|
+
/**
|
|
50
|
+
* Repository-relative file path, when the finding is file-anchored.
|
|
51
|
+
*/
|
|
52
|
+
path?: string;
|
|
53
|
+
/**
|
|
54
|
+
* 1-based line number, when the finding is line-anchored.
|
|
55
|
+
*/
|
|
56
|
+
line?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Human-readable finding description. Secret values are never included — only locations.
|
|
59
|
+
*/
|
|
60
|
+
message: string;
|
|
61
|
+
/**
|
|
62
|
+
* Suggested fix, when the tool provides one.
|
|
63
|
+
*/
|
|
64
|
+
remediation?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface EvidenceRef {
|
|
67
|
+
/**
|
|
68
|
+
* S3 bucket holding the full evidence object.
|
|
69
|
+
*/
|
|
70
|
+
bucket: string;
|
|
71
|
+
/**
|
|
72
|
+
* S3 key of the full evidence object, e.g. security-evidence/<org>/<app>/<env>/<commit>/<scannedAt>.json.
|
|
73
|
+
*/
|
|
74
|
+
key: string;
|
|
75
|
+
}
|
|
76
|
+
export interface Provenance {
|
|
77
|
+
org: string;
|
|
78
|
+
app: string;
|
|
79
|
+
env: 'preview' | 'prod';
|
|
80
|
+
repo: string;
|
|
81
|
+
commit: string;
|
|
82
|
+
branch: string;
|
|
83
|
+
/**
|
|
84
|
+
* SHA-256 of the exact source snapshot tarball that was scanned, verified before extraction.
|
|
85
|
+
*/
|
|
86
|
+
snapshotSha256: string;
|
|
87
|
+
/**
|
|
88
|
+
* UTC timestamp the scan completed.
|
|
89
|
+
*/
|
|
90
|
+
scannedAt: string;
|
|
91
|
+
/**
|
|
92
|
+
* Digest of the runner image's tool-manifest.json — pins which tool versions produced this evidence.
|
|
93
|
+
*/
|
|
94
|
+
toolManifestDigest: string;
|
|
95
|
+
/**
|
|
96
|
+
* True iff the input omitted classification and the machine assumed STANDARD (decision 2026-08-27). An invalid classification fails closed and never reaches a verdict.
|
|
97
|
+
*/
|
|
98
|
+
classificationDefaulted: boolean;
|
|
99
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Structured output an agent must return from one Harbour transformation attempt. Handed to the agent as its output schema, then decoded and semantically re-validated by the control plane, which remains the authority. The enum on applied_playbooks.items is the one dynamic part: the adapter injects the names of the playbooks supplied for that invocation before writing the document, so the model is structurally prevented from naming a playbook it was not given. Application-secret handling was removed platform-wide, so this document carries no redactions and no secrets fields.
|
|
3
3
|
*/
|
|
4
|
-
export
|
|
4
|
+
export type TransformReport = {
|
|
5
5
|
/**
|
|
6
6
|
* @minItems 1
|
|
7
7
|
*/
|
|
8
|
-
applied_playbooks
|
|
9
|
-
static_rebuild_required
|
|
10
|
-
analysis
|
|
8
|
+
applied_playbooks?: string[];
|
|
9
|
+
static_rebuild_required?: boolean;
|
|
10
|
+
analysis?: {
|
|
11
11
|
deployable: boolean;
|
|
12
12
|
needsTransformation: boolean;
|
|
13
13
|
/**
|
|
@@ -28,7 +28,7 @@ export interface TransformReport {
|
|
|
28
28
|
reason: string;
|
|
29
29
|
}[];
|
|
30
30
|
};
|
|
31
|
-
database
|
|
31
|
+
database?: {
|
|
32
32
|
mode: 'none' | 'sql' | 'unsupported';
|
|
33
33
|
changeType: 'none' | 'code_only' | 'schema_only' | 'code_and_schema';
|
|
34
34
|
requiresCodeChanges: boolean;
|
|
@@ -56,15 +56,20 @@ export interface TransformReport {
|
|
|
56
56
|
unsupportedFeatures: string[];
|
|
57
57
|
};
|
|
58
58
|
application: {
|
|
59
|
-
|
|
59
|
+
unsupported?: {
|
|
60
|
+
capability: string;
|
|
61
|
+
constraint: string;
|
|
62
|
+
reason: string;
|
|
63
|
+
};
|
|
64
|
+
runtime?: string;
|
|
60
65
|
/**
|
|
61
66
|
* Optional reviewed runtime features selected for the standard application image. The first release supports Chromium for Node runtimes only.
|
|
62
67
|
*/
|
|
63
68
|
runtimeFeatures?: 'chromium'[];
|
|
64
|
-
buildKind
|
|
65
|
-
topology
|
|
66
|
-
entrypoint
|
|
67
|
-
build
|
|
69
|
+
buildKind?: 'container' | 'static';
|
|
70
|
+
topology?: 'static' | 'backend' | 'frontend_and_backend';
|
|
71
|
+
entrypoint?: string;
|
|
72
|
+
build?: {
|
|
68
73
|
/**
|
|
69
74
|
* @minItems 1
|
|
70
75
|
* @maxItems 64
|
|
@@ -85,7 +90,7 @@ export interface TransformReport {
|
|
|
85
90
|
route: string;
|
|
86
91
|
}[];
|
|
87
92
|
};
|
|
88
|
-
basePath
|
|
93
|
+
basePath?: {
|
|
89
94
|
required: boolean;
|
|
90
95
|
environmentVariable: 'HARBOUR_BASE_PATH';
|
|
91
96
|
};
|
|
@@ -93,7 +98,7 @@ export interface TransformReport {
|
|
|
93
98
|
* @minItems 1
|
|
94
99
|
* @maxItems 64
|
|
95
100
|
*/
|
|
96
|
-
evidence
|
|
101
|
+
evidence?: {
|
|
97
102
|
path: string;
|
|
98
103
|
line: number;
|
|
99
104
|
reason: string;
|
|
@@ -101,6 +106,14 @@ export interface TransformReport {
|
|
|
101
106
|
/**
|
|
102
107
|
* @maxItems 64
|
|
103
108
|
*/
|
|
104
|
-
unsupportedFeatures
|
|
109
|
+
unsupportedFeatures?: string[];
|
|
110
|
+
};
|
|
111
|
+
} & ({
|
|
112
|
+
application: {
|
|
113
|
+
[k: string]: unknown;
|
|
114
|
+
};
|
|
115
|
+
} | {
|
|
116
|
+
application?: {
|
|
117
|
+
[k: string]: unknown;
|
|
105
118
|
};
|
|
106
|
-
}
|
|
119
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
3
|
|
|
4
|
-
export const ContractRepositoryVersion = "0.
|
|
5
|
-
export const ContractPublishVersion = "0.
|
|
6
|
-
export const ContractPublishTag = "v0.
|
|
7
|
-
export const ContractSchemasDigest = "sha256:
|
|
4
|
+
export const ContractRepositoryVersion = "0.26.0.0" as const;
|
|
5
|
+
export const ContractPublishVersion = "0.26.0" as const;
|
|
6
|
+
export const ContractPublishTag = "v0.26.0" as const;
|
|
7
|
+
export const ContractSchemasDigest = "sha256:510b57798fd632a4fd34ea7701106b03285c491ab1eddbdef7d1ec0f82d7f70c" as const;
|
|
8
8
|
export const ContractAiFixturesDigest = "sha256:5d68828a1364dc63cafbb3c2d3f5c5f6c232d5333e7668a9c79e7652e5144b42" as const;
|
|
9
|
-
export const ContractGeneratedGoDigest = "sha256:
|
|
10
|
-
export const ContractGeneratedTypeScriptDigest = "sha256:
|
|
9
|
+
export const ContractGeneratedGoDigest = "sha256:02a598e4606a1d24bbfdd881e548128ce9b60c090db7ff98dcee5bfe94b74ad3" as const;
|
|
10
|
+
export const ContractGeneratedTypeScriptDigest = "sha256:72865190987cb97215b1db19d46e5c54579f2c01677e5b8e5c735df1d669b74b" as const;
|
package/gen-ts/deploy-request.ts
CHANGED
|
@@ -58,6 +58,7 @@ export interface DeployRequest {
|
|
|
58
58
|
* Preview-only. When true, the transformed code is NOT committed back to the source branch (benchmark deploys). Ignored outside preview.
|
|
59
59
|
*/
|
|
60
60
|
benchRun?: boolean;
|
|
61
|
+
transform?: DeployRequestTransform;
|
|
61
62
|
bindingClassification: BindingClassificationSubject;
|
|
62
63
|
}
|
|
63
64
|
export interface DeployRequestSource {
|
|
@@ -79,6 +80,15 @@ export interface DeployRequestEnvironmentBindings {
|
|
|
79
80
|
*/
|
|
80
81
|
bindings: DeployRequestEnvironmentBinding[];
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Optional transformation-engine selection. Absence preserves the existing sequential engine.
|
|
85
|
+
*/
|
|
86
|
+
export interface DeployRequestTransform {
|
|
87
|
+
/**
|
|
88
|
+
* Transformation engine. Omit to preserve the existing sequential default.
|
|
89
|
+
*/
|
|
90
|
+
strategy?: 'sequential' | 'branch_select';
|
|
91
|
+
}
|
|
82
92
|
/**
|
|
83
93
|
* Complete pre-allocation, value-free binding-name classification. DCP verifies its tenant/app/environment/source identity and exact name coverage before minting the versionId.
|
|
84
94
|
*/
|
|
@@ -28,6 +28,10 @@ export interface DeploymentStatusResponse {
|
|
|
28
28
|
commit: string;
|
|
29
29
|
requestedAt: string;
|
|
30
30
|
updatedAt: string;
|
|
31
|
+
/**
|
|
32
|
+
* Transformation engine persisted for this immutable version. Older stored versions are projected as sequential.
|
|
33
|
+
*/
|
|
34
|
+
transformStrategy: 'sequential' | 'branch_select';
|
|
31
35
|
url?: string;
|
|
32
36
|
failure?: StatusFailureProjection;
|
|
33
37
|
/**
|
|
@@ -64,4 +68,14 @@ export interface StatusProgressEvent {
|
|
|
64
68
|
* Short frontend-safe detail. Like the failure projection, it carries no internal identifiers, raw provider errors or secrets.
|
|
65
69
|
*/
|
|
66
70
|
detail?: string;
|
|
71
|
+
strategy?: 'branch_select';
|
|
72
|
+
knowledgeVersion?: string;
|
|
73
|
+
branchId?: string;
|
|
74
|
+
action?: 'continue' | 'widen' | 'kill' | 'unsupported';
|
|
75
|
+
planConfidence?: 'high' | 'medium' | 'low';
|
|
76
|
+
optionCount?: number;
|
|
77
|
+
depth?: number;
|
|
78
|
+
failureCategory?: string;
|
|
79
|
+
remainingMs?: number;
|
|
80
|
+
origin?: 'initial' | 'widen';
|
|
67
81
|
}
|
|
@@ -12,6 +12,7 @@ export const ErrorCategories = {
|
|
|
12
12
|
SecretsLeakedInArtifact: "secrets.leaked-in-artifact",
|
|
13
13
|
StorageSqliteMisclassified: "storage.sqlite-misclassified",
|
|
14
14
|
StorageMappingDrift: "storage.mapping-drift",
|
|
15
|
+
StorageUnavailable: "storage.unavailable",
|
|
15
16
|
TransformDeadlineExceeded: "transform.deadline-exceeded",
|
|
16
17
|
TransformValidationFailed: "transform.validation-failed",
|
|
17
18
|
FrontendEnvInlinedUnfixable: "frontend.env-inlined-unfixable",
|
|
@@ -56,6 +57,7 @@ const retryableExact: Record<string, boolean> = {
|
|
|
56
57
|
"secrets.leaked-in-artifact": false,
|
|
57
58
|
"storage.sqlite-misclassified": false,
|
|
58
59
|
"storage.mapping-drift": false,
|
|
60
|
+
"storage.unavailable": true,
|
|
59
61
|
"transform.deadline-exceeded": false,
|
|
60
62
|
"transform.validation-failed": true,
|
|
61
63
|
"frontend.env-inlined-unfixable": false,
|
package/gen-ts/index.ts
CHANGED
|
@@ -46,6 +46,8 @@ export * from './promotion-response.js';
|
|
|
46
46
|
export * from './sanitized-binding-digest-helper.js';
|
|
47
47
|
export * from './sanitized-binding-evidence.js';
|
|
48
48
|
export * from './secret-reference.js';
|
|
49
|
+
export * from './security-scan-input.js';
|
|
50
|
+
export * from './security-verdict.js';
|
|
49
51
|
export * from './transform-report.js';
|
|
50
52
|
export * from './version-state-machine.js';
|
|
51
53
|
export * from './version-state.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Input to the Harbour Security Assurance machine (Security Assurance LLD §2). M1 runs the SOURCE phase only; ARTIFACT is reserved in the enum so the contract is stable through M2. `commit` is the identity being scanned; `org/app/env` locate the snapshot (the control-state table has no commit GSI, so a bare commit is not resolvable); `branch` is caller-supplied provenance.
|
|
6
|
+
*/
|
|
7
|
+
export interface SecurityScanInput {
|
|
8
|
+
/**
|
|
9
|
+
* Scan phase. M1 implements SOURCE only; ARTIFACT is reserved for M2 (image scan against an ECR digest) and is rejected by the machine until then.
|
|
10
|
+
*/
|
|
11
|
+
phase: 'SOURCE' | 'ARTIFACT';
|
|
12
|
+
/**
|
|
13
|
+
* Harbour organization id, e.g. fourier.
|
|
14
|
+
*/
|
|
15
|
+
org: string;
|
|
16
|
+
/**
|
|
17
|
+
* Harbour app id within the org, e.g. focuslist.
|
|
18
|
+
*/
|
|
19
|
+
app: string;
|
|
20
|
+
/**
|
|
21
|
+
* Environment whose ingested snapshots are searched for the commit. M1 deploys preview-only; prod is contract-stable for M3.
|
|
22
|
+
*/
|
|
23
|
+
env: 'preview' | 'prod';
|
|
24
|
+
/**
|
|
25
|
+
* GitHub owner/name of the source repository, e.g. Fourier-Labs-AI/focus-list.
|
|
26
|
+
*/
|
|
27
|
+
repo: string;
|
|
28
|
+
/**
|
|
29
|
+
* Full 40-hex lowercase commit SHA — the identity being scanned.
|
|
30
|
+
*/
|
|
31
|
+
commit: string;
|
|
32
|
+
/**
|
|
33
|
+
* Branch name, supplied authoritatively by the caller in v1 (provenance only — never used for resolution).
|
|
34
|
+
*/
|
|
35
|
+
branch: string;
|
|
36
|
+
/**
|
|
37
|
+
* Data classification of the app. Optional in v1 (decided 2026-08-27): when ABSENT the machine assumes the STANDARD profile and stamps classificationDefaulted: true in the verdict provenance. An invalid value still fails closed — only absence defaults. No classifier exists until M4; until then callers state it or accept the default.
|
|
38
|
+
*/
|
|
39
|
+
classification?: 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED';
|
|
40
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Decision produced by the Harbour Security Assurance machine (Security Assurance LLD §2). `outcome: BLOCKED` surfaces to callers as the registered non-retryable `gate.security-scan` error category; `reason` is present exactly when BLOCKED. The S3 evidence object named by `evidenceRef` is the full record — in-payload findings may be truncated.
|
|
6
|
+
*/
|
|
7
|
+
export interface SecurityVerdict {
|
|
8
|
+
/**
|
|
9
|
+
* Fail-closed decision: any missing or UNAVAILABLE required evidence is BLOCKED, never PASS.
|
|
10
|
+
*/
|
|
11
|
+
outcome: 'PASS' | 'BLOCKED';
|
|
12
|
+
/**
|
|
13
|
+
* Policy profile the evidence was evaluated against (derived from the input classification; STANDARD when the classification was absent).
|
|
14
|
+
*/
|
|
15
|
+
profile: 'BASELINE' | 'STANDARD' | 'HIGH' | 'CRITICAL';
|
|
16
|
+
/**
|
|
17
|
+
* Human-readable cause, present when outcome is BLOCKED; becomes the Fail-state cause of HarbourSecurityBlocked.
|
|
18
|
+
*/
|
|
19
|
+
reason?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Map of scan-category (e.g. source-secrets, dependency-sca) to its evidence. Kept as an open map so new categories (M2+) are additive, not a schema change.
|
|
22
|
+
*/
|
|
23
|
+
evidence: {
|
|
24
|
+
[k: string]: ScanEvidence;
|
|
25
|
+
};
|
|
26
|
+
evidenceRef: EvidenceRef;
|
|
27
|
+
provenance: Provenance;
|
|
28
|
+
}
|
|
29
|
+
export interface ScanEvidence {
|
|
30
|
+
/**
|
|
31
|
+
* UNAVAILABLE means the tool did not run or did not produce parseable output; policy treats it as blocking for required categories.
|
|
32
|
+
*/
|
|
33
|
+
status: 'PASS' | 'FAIL' | 'UNAVAILABLE';
|
|
34
|
+
/**
|
|
35
|
+
* Normalized, deduplicated findings. May be truncated in-payload; the S3 evidence object is complete.
|
|
36
|
+
*/
|
|
37
|
+
findings: Finding[];
|
|
38
|
+
}
|
|
39
|
+
export interface Finding {
|
|
40
|
+
/**
|
|
41
|
+
* Producing tool, e.g. gitleaks, trivy.
|
|
42
|
+
*/
|
|
43
|
+
tool: string;
|
|
44
|
+
/**
|
|
45
|
+
* Tool-native rule or vulnerability id, e.g. aws-access-key-id, CVE-2024-12345.
|
|
46
|
+
*/
|
|
47
|
+
ruleId: string;
|
|
48
|
+
/**
|
|
49
|
+
* Tool-native severity, normalized upper-case, e.g. CRITICAL, HIGH.
|
|
50
|
+
*/
|
|
51
|
+
severity: string;
|
|
52
|
+
/**
|
|
53
|
+
* Repository-relative file path, when the finding is file-anchored.
|
|
54
|
+
*/
|
|
55
|
+
path?: string;
|
|
56
|
+
/**
|
|
57
|
+
* 1-based line number, when the finding is line-anchored.
|
|
58
|
+
*/
|
|
59
|
+
line?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Human-readable finding description. Secret values are never included — only locations.
|
|
62
|
+
*/
|
|
63
|
+
message: string;
|
|
64
|
+
/**
|
|
65
|
+
* Suggested fix, when the tool provides one.
|
|
66
|
+
*/
|
|
67
|
+
remediation?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface EvidenceRef {
|
|
70
|
+
/**
|
|
71
|
+
* S3 bucket holding the full evidence object.
|
|
72
|
+
*/
|
|
73
|
+
bucket: string;
|
|
74
|
+
/**
|
|
75
|
+
* S3 key of the full evidence object, e.g. security-evidence/<org>/<app>/<env>/<commit>/<scannedAt>.json.
|
|
76
|
+
*/
|
|
77
|
+
key: string;
|
|
78
|
+
}
|
|
79
|
+
export interface Provenance {
|
|
80
|
+
org: string;
|
|
81
|
+
app: string;
|
|
82
|
+
env: 'preview' | 'prod';
|
|
83
|
+
repo: string;
|
|
84
|
+
commit: string;
|
|
85
|
+
branch: string;
|
|
86
|
+
/**
|
|
87
|
+
* SHA-256 of the exact source snapshot tarball that was scanned, verified before extraction.
|
|
88
|
+
*/
|
|
89
|
+
snapshotSha256: string;
|
|
90
|
+
/**
|
|
91
|
+
* UTC timestamp the scan completed.
|
|
92
|
+
*/
|
|
93
|
+
scannedAt: string;
|
|
94
|
+
/**
|
|
95
|
+
* Digest of the runner image's tool-manifest.json — pins which tool versions produced this evidence.
|
|
96
|
+
*/
|
|
97
|
+
toolManifestDigest: string;
|
|
98
|
+
/**
|
|
99
|
+
* True iff the input omitted classification and the machine assumed STANDARD (decision 2026-08-27). An invalid classification fails closed and never reaches a verdict.
|
|
100
|
+
*/
|
|
101
|
+
classificationDefaulted: boolean;
|
|
102
|
+
}
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Structured output an agent must return from one Harbour transformation attempt. Handed to the agent as its output schema, then decoded and semantically re-validated by the control plane, which remains the authority. The enum on applied_playbooks.items is the one dynamic part: the adapter injects the names of the playbooks supplied for that invocation before writing the document, so the model is structurally prevented from naming a playbook it was not given. Application-secret handling was removed platform-wide, so this document carries no redactions and no secrets fields.
|
|
6
6
|
*/
|
|
7
|
-
export
|
|
7
|
+
export type TransformReport = {
|
|
8
8
|
/**
|
|
9
9
|
* @minItems 1
|
|
10
10
|
*/
|
|
11
|
-
applied_playbooks
|
|
12
|
-
static_rebuild_required
|
|
13
|
-
analysis
|
|
11
|
+
applied_playbooks?: string[];
|
|
12
|
+
static_rebuild_required?: boolean;
|
|
13
|
+
analysis?: {
|
|
14
14
|
deployable: boolean;
|
|
15
15
|
needsTransformation: boolean;
|
|
16
16
|
/**
|
|
@@ -31,7 +31,7 @@ export interface TransformReport {
|
|
|
31
31
|
reason: string;
|
|
32
32
|
}[];
|
|
33
33
|
};
|
|
34
|
-
database
|
|
34
|
+
database?: {
|
|
35
35
|
mode: 'none' | 'sql' | 'unsupported';
|
|
36
36
|
changeType: 'none' | 'code_only' | 'schema_only' | 'code_and_schema';
|
|
37
37
|
requiresCodeChanges: boolean;
|
|
@@ -59,15 +59,20 @@ export interface TransformReport {
|
|
|
59
59
|
unsupportedFeatures: string[];
|
|
60
60
|
};
|
|
61
61
|
application: {
|
|
62
|
-
|
|
62
|
+
unsupported?: {
|
|
63
|
+
capability: string;
|
|
64
|
+
constraint: string;
|
|
65
|
+
reason: string;
|
|
66
|
+
};
|
|
67
|
+
runtime?: string;
|
|
63
68
|
/**
|
|
64
69
|
* Optional reviewed runtime features selected for the standard application image. The first release supports Chromium for Node runtimes only.
|
|
65
70
|
*/
|
|
66
71
|
runtimeFeatures?: 'chromium'[];
|
|
67
|
-
buildKind
|
|
68
|
-
topology
|
|
69
|
-
entrypoint
|
|
70
|
-
build
|
|
72
|
+
buildKind?: 'container' | 'static';
|
|
73
|
+
topology?: 'static' | 'backend' | 'frontend_and_backend';
|
|
74
|
+
entrypoint?: string;
|
|
75
|
+
build?: {
|
|
71
76
|
/**
|
|
72
77
|
* @minItems 1
|
|
73
78
|
* @maxItems 64
|
|
@@ -88,7 +93,7 @@ export interface TransformReport {
|
|
|
88
93
|
route: string;
|
|
89
94
|
}[];
|
|
90
95
|
};
|
|
91
|
-
basePath
|
|
96
|
+
basePath?: {
|
|
92
97
|
required: boolean;
|
|
93
98
|
environmentVariable: 'HARBOUR_BASE_PATH';
|
|
94
99
|
};
|
|
@@ -96,7 +101,7 @@ export interface TransformReport {
|
|
|
96
101
|
* @minItems 1
|
|
97
102
|
* @maxItems 64
|
|
98
103
|
*/
|
|
99
|
-
evidence
|
|
104
|
+
evidence?: {
|
|
100
105
|
path: string;
|
|
101
106
|
line: number;
|
|
102
107
|
reason: string;
|
|
@@ -104,6 +109,17 @@ export interface TransformReport {
|
|
|
104
109
|
/**
|
|
105
110
|
* @maxItems 64
|
|
106
111
|
*/
|
|
107
|
-
unsupportedFeatures
|
|
112
|
+
unsupportedFeatures?: string[];
|
|
108
113
|
};
|
|
109
|
-
}
|
|
114
|
+
} & (
|
|
115
|
+
| {
|
|
116
|
+
application: {
|
|
117
|
+
[k: string]: unknown;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
| {
|
|
121
|
+
application?: {
|
|
122
|
+
[k: string]: unknown;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
);
|
package/package.json
CHANGED
|
@@ -39,12 +39,27 @@
|
|
|
39
39
|
"default": false,
|
|
40
40
|
"description": "Preview-only. When true, the transformed code is NOT committed back to the source branch (benchmark deploys). Ignored outside preview."
|
|
41
41
|
},
|
|
42
|
+
"transform": {
|
|
43
|
+
"$ref": "#/definitions/DeployRequestTransform",
|
|
44
|
+
"description": "Optional transformation-engine selection. Absence preserves the existing sequential engine."
|
|
45
|
+
},
|
|
42
46
|
"bindingClassification": {
|
|
43
47
|
"$ref": "binding-classification-subject.schema.json",
|
|
44
48
|
"description": "Complete pre-allocation, value-free binding-name classification. DCP verifies its tenant/app/environment/source identity and exact name coverage before minting the versionId."
|
|
45
49
|
}
|
|
46
50
|
},
|
|
47
51
|
"definitions": {
|
|
52
|
+
"DeployRequestTransform": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"properties": {
|
|
56
|
+
"strategy": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["sequential", "branch_select"],
|
|
59
|
+
"description": "Transformation engine. Omit to preserve the existing sequential default."
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
48
63
|
"DeployRequestEnvironmentBindings": {
|
|
49
64
|
"type": "object",
|
|
50
65
|
"additionalProperties": false,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "200 OK body returned by GET /v1/tenants/{tenant}/apps/{app}/deployments/{versionId}. It describes that exact immutable version; newer deployments cannot change which record this response represents.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
|
-
"required": ["requestId", "versionId", "tenant", "app", "environment", "status", "message", "branch", "commit", "requestedAt", "updatedAt"],
|
|
8
|
+
"required": ["requestId", "versionId", "tenant", "app", "environment", "status", "message", "branch", "commit", "requestedAt", "updatedAt", "transformStrategy"],
|
|
9
9
|
"properties": {
|
|
10
10
|
"requestId": {
|
|
11
11
|
"type": "string"
|
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
"type": "string",
|
|
47
47
|
"format": "date-time"
|
|
48
48
|
},
|
|
49
|
+
"transformStrategy": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"enum": ["sequential", "branch_select"],
|
|
52
|
+
"description": "Transformation engine persisted for this immutable version. Older stored versions are projected as sequential."
|
|
53
|
+
},
|
|
49
54
|
"url": {
|
|
50
55
|
"type": "string",
|
|
51
56
|
"format": "uri"
|
|
@@ -113,7 +118,17 @@
|
|
|
113
118
|
"type": "string",
|
|
114
119
|
"maxLength": 256,
|
|
115
120
|
"description": "Short frontend-safe detail. Like the failure projection, it carries no internal identifiers, raw provider errors or secrets."
|
|
116
|
-
}
|
|
121
|
+
},
|
|
122
|
+
"strategy": { "type": "string", "enum": ["branch_select"] },
|
|
123
|
+
"knowledgeVersion": { "type": "string", "pattern": "^v[0-9]+$" },
|
|
124
|
+
"branchId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[a-z0-9][a-z0-9.-]*$" },
|
|
125
|
+
"action": { "type": "string", "enum": ["continue", "widen", "kill", "unsupported"] },
|
|
126
|
+
"planConfidence": { "type": "string", "enum": ["high", "medium", "low"] },
|
|
127
|
+
"optionCount": { "type": "integer", "minimum": 1, "maximum": 64 },
|
|
128
|
+
"depth": { "type": "integer", "minimum": 1, "maximum": 10000 },
|
|
129
|
+
"failureCategory": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[a-z0-9][a-z0-9.-]*$" },
|
|
130
|
+
"remainingMs": { "type": "integer", "minimum": 1, "maximum": 86400000 },
|
|
131
|
+
"origin": { "type": "string", "enum": ["initial", "widen"] }
|
|
117
132
|
}
|
|
118
133
|
}
|
|
119
134
|
}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
{ "id": "storage.sqlite-misclassified", "retryable": false, "description": "SQLite usage not resolvable to a managed binding." },
|
|
24
24
|
{ "id": "storage.unsupported-engine", "retryable": false, "family": true, "description": "Storage engine with no Harbour mapping; concrete token names the engine, e.g. storage.unsupported-engine.mongodb." },
|
|
25
25
|
{ "id": "storage.mapping-drift", "retryable": false, "description": "Declared storage binding diverged from detected usage." },
|
|
26
|
+
{ "id": "storage.unavailable", "retryable": true, "description": "The platform's shared application database could not be reached while preparing or provisioning the deploy — e.g. the Aurora cluster dial timing out during a scale-from-zero cold start. Says nothing about the app, so it IS retryable: the same deploy submitted again is expected to succeed once the database is awake. Previously surfaced as uncategorized.deploy (errorType wrapError)." },
|
|
26
27
|
{ "id": "transform.deadline-exceeded", "retryable": false, "description": "The 15-minute transform wall deadline was reached." },
|
|
27
28
|
{ "id": "transform.non-retryable", "retryable": false, "family": true, "description": "Agent declared the app unconvertible or hit an unsupported construct; fails immediately without burning remaining budget. Concrete token names the reason." },
|
|
28
29
|
{ "id": "transform.validation-failed", "retryable": true, "description": "Transform candidate failed validation with iterable feedback; re-enters TRANSFORMING while deadline remains." },
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://schemas.harbour.dev/security-scan-input.schema.json",
|
|
4
|
+
"title": "SecurityScanInput",
|
|
5
|
+
"description": "Input to the Harbour Security Assurance machine (Security Assurance LLD §2). M1 runs the SOURCE phase only; ARTIFACT is reserved in the enum so the contract is stable through M2. `commit` is the identity being scanned; `org/app/env` locate the snapshot (the control-state table has no commit GSI, so a bare commit is not resolvable); `branch` is caller-supplied provenance.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["phase", "org", "app", "env", "repo", "commit", "branch"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"phase": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["SOURCE", "ARTIFACT"],
|
|
13
|
+
"description": "Scan phase. M1 implements SOURCE only; ARTIFACT is reserved for M2 (image scan against an ECR digest) and is rejected by the machine until then."
|
|
14
|
+
},
|
|
15
|
+
"org": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1,
|
|
18
|
+
"description": "Harbour organization id, e.g. fourier."
|
|
19
|
+
},
|
|
20
|
+
"app": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"description": "Harbour app id within the org, e.g. focuslist."
|
|
24
|
+
},
|
|
25
|
+
"env": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": ["preview", "prod"],
|
|
28
|
+
"description": "Environment whose ingested snapshots are searched for the commit. M1 deploys preview-only; prod is contract-stable for M3."
|
|
29
|
+
},
|
|
30
|
+
"repo": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1,
|
|
33
|
+
"pattern": "^[^/\\s]+/[^/\\s]+$",
|
|
34
|
+
"description": "GitHub owner/name of the source repository, e.g. Fourier-Labs-AI/focus-list."
|
|
35
|
+
},
|
|
36
|
+
"commit": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"pattern": "^[0-9a-f]{40}$",
|
|
39
|
+
"description": "Full 40-hex lowercase commit SHA — the identity being scanned."
|
|
40
|
+
},
|
|
41
|
+
"branch": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 1,
|
|
44
|
+
"description": "Branch name, supplied authoritatively by the caller in v1 (provenance only — never used for resolution)."
|
|
45
|
+
},
|
|
46
|
+
"classification": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"enum": ["GREEN", "YELLOW", "ORANGE", "RED"],
|
|
49
|
+
"description": "Data classification of the app. Optional in v1 (decided 2026-08-27): when ABSENT the machine assumes the STANDARD profile and stamps classificationDefaulted: true in the verdict provenance. An invalid value still fails closed — only absence defaults. No classifier exists until M4; until then callers state it or accept the default."
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://schemas.harbour.dev/security-verdict.schema.json",
|
|
4
|
+
"title": "SecurityVerdict",
|
|
5
|
+
"description": "Decision produced by the Harbour Security Assurance machine (Security Assurance LLD §2). `outcome: BLOCKED` surfaces to callers as the registered non-retryable `gate.security-scan` error category; `reason` is present exactly when BLOCKED. The S3 evidence object named by `evidenceRef` is the full record — in-payload findings may be truncated.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["outcome", "profile", "evidence", "evidenceRef", "provenance"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"outcome": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["PASS", "BLOCKED"],
|
|
13
|
+
"description": "Fail-closed decision: any missing or UNAVAILABLE required evidence is BLOCKED, never PASS."
|
|
14
|
+
},
|
|
15
|
+
"profile": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"enum": ["BASELINE", "STANDARD", "HIGH", "CRITICAL"],
|
|
18
|
+
"description": "Policy profile the evidence was evaluated against (derived from the input classification; STANDARD when the classification was absent)."
|
|
19
|
+
},
|
|
20
|
+
"reason": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"description": "Human-readable cause, present when outcome is BLOCKED; becomes the Fail-state cause of HarbourSecurityBlocked."
|
|
24
|
+
},
|
|
25
|
+
"evidence": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": { "$ref": "#/definitions/ScanEvidence" },
|
|
28
|
+
"description": "Map of scan-category (e.g. source-secrets, dependency-sca) to its evidence. Kept as an open map so new categories (M2+) are additive, not a schema change."
|
|
29
|
+
},
|
|
30
|
+
"evidenceRef": { "$ref": "#/definitions/EvidenceRef" },
|
|
31
|
+
"provenance": { "$ref": "#/definitions/Provenance" }
|
|
32
|
+
},
|
|
33
|
+
"definitions": {
|
|
34
|
+
"ScanEvidence": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"additionalProperties": false,
|
|
37
|
+
"required": ["status", "findings"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"status": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"enum": ["PASS", "FAIL", "UNAVAILABLE"],
|
|
42
|
+
"description": "UNAVAILABLE means the tool did not run or did not produce parseable output; policy treats it as blocking for required categories."
|
|
43
|
+
},
|
|
44
|
+
"findings": {
|
|
45
|
+
"type": "array",
|
|
46
|
+
"items": { "$ref": "#/definitions/Finding" },
|
|
47
|
+
"description": "Normalized, deduplicated findings. May be truncated in-payload; the S3 evidence object is complete."
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"Finding": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"required": ["tool", "ruleId", "severity", "message"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"tool": { "type": "string", "minLength": 1, "description": "Producing tool, e.g. gitleaks, trivy." },
|
|
57
|
+
"ruleId": { "type": "string", "minLength": 1, "description": "Tool-native rule or vulnerability id, e.g. aws-access-key-id, CVE-2024-12345." },
|
|
58
|
+
"severity": { "type": "string", "minLength": 1, "description": "Tool-native severity, normalized upper-case, e.g. CRITICAL, HIGH." },
|
|
59
|
+
"path": { "type": "string", "description": "Repository-relative file path, when the finding is file-anchored." },
|
|
60
|
+
"line": { "type": "integer", "minimum": 1, "description": "1-based line number, when the finding is line-anchored." },
|
|
61
|
+
"message": { "type": "string", "minLength": 1, "description": "Human-readable finding description. Secret values are never included — only locations." },
|
|
62
|
+
"remediation": { "type": "string", "description": "Suggested fix, when the tool provides one." }
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"EvidenceRef": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"required": ["bucket", "key"],
|
|
69
|
+
"properties": {
|
|
70
|
+
"bucket": { "type": "string", "minLength": 1, "description": "S3 bucket holding the full evidence object." },
|
|
71
|
+
"key": { "type": "string", "minLength": 1, "description": "S3 key of the full evidence object, e.g. security-evidence/<org>/<app>/<env>/<commit>/<scannedAt>.json." }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"Provenance": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"required": ["org", "app", "env", "repo", "commit", "branch", "snapshotSha256", "scannedAt", "toolManifestDigest", "classificationDefaulted"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"org": { "type": "string", "minLength": 1 },
|
|
80
|
+
"app": { "type": "string", "minLength": 1 },
|
|
81
|
+
"env": { "type": "string", "enum": ["preview", "prod"] },
|
|
82
|
+
"repo": { "type": "string", "minLength": 1, "pattern": "^[^/\\s]+/[^/\\s]+$" },
|
|
83
|
+
"commit": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
|
|
84
|
+
"branch": { "type": "string", "minLength": 1 },
|
|
85
|
+
"snapshotSha256": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"pattern": "^[0-9a-f]{64}$",
|
|
88
|
+
"description": "SHA-256 of the exact source snapshot tarball that was scanned, verified before extraction."
|
|
89
|
+
},
|
|
90
|
+
"scannedAt": { "type": "string", "format": "date-time", "description": "UTC timestamp the scan completed." },
|
|
91
|
+
"toolManifestDigest": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "Digest of the runner image's tool-manifest.json — pins which tool versions produced this evidence."
|
|
94
|
+
},
|
|
95
|
+
"classificationDefaulted": {
|
|
96
|
+
"type": "boolean",
|
|
97
|
+
"description": "True iff the input omitted classification and the machine assumed STANDARD (decision 2026-08-27). An invalid classification fails closed and never reaches a verdict."
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -6,13 +6,7 @@
|
|
|
6
6
|
"x-go-embed": true,
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
|
9
|
-
"required": [
|
|
10
|
-
"applied_playbooks",
|
|
11
|
-
"static_rebuild_required",
|
|
12
|
-
"analysis",
|
|
13
|
-
"database",
|
|
14
|
-
"application"
|
|
15
|
-
],
|
|
9
|
+
"required": ["application"],
|
|
16
10
|
"properties": {
|
|
17
11
|
"applied_playbooks": {
|
|
18
12
|
"type": "array",
|
|
@@ -111,17 +105,17 @@
|
|
|
111
105
|
"application": {
|
|
112
106
|
"type": "object",
|
|
113
107
|
"additionalProperties": false,
|
|
114
|
-
"required": [
|
|
115
|
-
"runtime",
|
|
116
|
-
"buildKind",
|
|
117
|
-
"topology",
|
|
118
|
-
"entrypoint",
|
|
119
|
-
"build",
|
|
120
|
-
"basePath",
|
|
121
|
-
"evidence",
|
|
122
|
-
"unsupportedFeatures"
|
|
123
|
-
],
|
|
124
108
|
"properties": {
|
|
109
|
+
"unsupported": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"additionalProperties": false,
|
|
112
|
+
"required": ["capability", "constraint", "reason"],
|
|
113
|
+
"properties": {
|
|
114
|
+
"capability": { "type": "string", "minLength": 1, "maxLength": 512 },
|
|
115
|
+
"constraint": { "type": "string", "minLength": 1, "maxLength": 512 },
|
|
116
|
+
"reason": { "type": "string", "minLength": 1, "maxLength": 2048 }
|
|
117
|
+
}
|
|
118
|
+
},
|
|
125
119
|
"runtime": {
|
|
126
120
|
"type": "string",
|
|
127
121
|
"pattern": "^(?:nodejs|python)[0-9]+(?:\\.[0-9]+)?$"
|
|
@@ -209,5 +203,25 @@
|
|
|
209
203
|
}
|
|
210
204
|
}
|
|
211
205
|
}
|
|
212
|
-
}
|
|
206
|
+
},
|
|
207
|
+
"oneOf": [
|
|
208
|
+
{
|
|
209
|
+
"required": ["applied_playbooks", "static_rebuild_required", "analysis", "database", "application"],
|
|
210
|
+
"properties": {
|
|
211
|
+
"application": {
|
|
212
|
+
"required": ["runtime", "buildKind", "topology", "entrypoint", "build", "basePath", "evidence", "unsupportedFeatures"],
|
|
213
|
+
"not": { "required": ["unsupported"] }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"maxProperties": 1,
|
|
219
|
+
"properties": {
|
|
220
|
+
"application": {
|
|
221
|
+
"required": ["unsupported"],
|
|
222
|
+
"maxProperties": 1
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
]
|
|
213
227
|
}
|