@fourier-labs/harbour-contracts 0.29.0 → 0.32.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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schema": "harbour.contract-release/1.0",
3
- "repositoryVersion": "0.29.0.0",
4
- "publishVersion": "0.29.0",
5
- "publishTag": "v0.29.0",
6
- "schemasDigest": "sha256:4b21ea9a6b13193a189d2499f6cc8f24975db18686e64d2042490a85dca669fc",
3
+ "repositoryVersion": "0.32.0.0",
4
+ "publishVersion": "0.32.0",
5
+ "publishTag": "v0.32.0",
6
+ "schemasDigest": "sha256:0476a253b6fe583fefeca0766502fbdb4f94987265c86268a489eb6ddfab4d29",
7
7
  "aiFixturesDigest": "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6",
8
- "generatedGoDigest": "sha256:6e5af7342005ceb5b2a175b3d5c3eb27e06fe5bfa57e74e2e854038b5f8cbad6",
9
- "generatedTypeScriptDigest": "sha256:b6201aeb54e733aaf4f33c2bdf75054b3e10b1616e031620cce15ee72fb37770",
8
+ "generatedGoDigest": "sha256:6bb7567f6e0a753136c8389ce8e3a0f8357d360c94ef6f3da3768e63d6562822",
9
+ "generatedTypeScriptDigest": "sha256:1f8c32cbe5fbf605bdcaeb73152977a92c488ebd1ab96fb4234a56eb9fc5cee7",
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)"
@@ -42,7 +42,7 @@
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:f3e3fb919279095e3f1b35302c549972537bfe9d4f3b305f14b1391f71e66e2c",
45
+ "schema/deployment-status-response.schema.json": "sha256:ce6b4e10a4302dff75c8958a3555f3a323e407e8cd2d2dce58550e7cb6cff1c8",
46
46
  "schema/env-bindings.schema.json": "sha256:ae09bc4ca5508afa698ef854a59153c4c6f99b07017b48cb9b07ce05abad12f2",
47
47
  "schema/error-category.enum.json": "sha256:693f8ce67d5554358f89b76132024cb8a082216f192d80a66bc4dc64e8983332",
48
48
  "schema/error-envelope.schema.json": "sha256:75dccda7dd16fdf8435deda53fc7dbcdc109b65114617a17f11763010c656f90",
@@ -51,10 +51,10 @@
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/security-scan-input.schema.json": "sha256:9f9c9e6131c1abee454320b77e4332e3780c0c63f108f54f75c93194a32ccff7",
54
+ "schema/security-scan-input.schema.json": "sha256:83502dffb3c07ac2e0698928e6dc123f454fc667d4aacd336bcad6944ef2ac3d",
55
55
  "schema/security-verdict.schema.json": "sha256:ec3c2d5c9df3601aeed0909b36c7f427469c7f0eeb3295c5809b96d09bf3fc26",
56
56
  "schema/transform-report.schema.json": "sha256:815e764445fb41b912d0c0468f00621ad61f941fb4c7b9364e3f204ad47cdf7f",
57
- "schema/version-state.schema.json": "sha256:e7c4b2e7b615ebb07f36d0df22ded51b2c9688ef9e9bfe79de1d5cd94de9ae40"
57
+ "schema/version-state.schema.json": "sha256:3b190007e2f8e3821c41ef11c6f5b226da7d5a18d34d4077f4618004846fd444"
58
58
  },
59
59
  "aiFixtures": {
60
60
  "fixtures/ai/adversarial-binding-classification-value.json": "sha256:ca009f3f6162a9d93b4ab416d52c1fba12a8a15aca5aed956c5fdcf2171b1e28",
@@ -89,12 +89,12 @@
89
89
  "gen-go/ai_contracts_test.go": "sha256:17ce967139e39c291ee7ebad3f66cc0495324abc4e56885279f7e5cc74994036",
90
90
  "gen-go/ai_gateway_key_token.go": "sha256:859c34383955f21c22589158214df074b74de6907a54bee7c781acfa9dad8679",
91
91
  "gen-go/binding_digest_helpers.go": "sha256:50462ba2beb16c7931dfc7e10302c12c90bf8111788991f74f08a718125dfbfb",
92
- "gen-go/contracts_test.go": "sha256:7c7ee46f2b4277e22b1ee21af9f17d201eb83067c613b049749f932706ed24f8",
92
+ "gen-go/contracts_test.go": "sha256:28d6bf1bdc57eb4297b45d542adbdca420c943f02166c5889824e81f530a8ad4",
93
93
  "gen-go/doc.go": "sha256:c17bc2d39ed175ce7105c68305f8ae7152f659eb7cd187ecceee7698eb3a65dd",
94
94
  "gen-go/error_category.go": "sha256:a8b64524be3716e62ca6016e56f2332a56fa5e16e42647421e516aa01a7d6806",
95
95
  "gen-go/schema_documents.go": "sha256:4b9094aaf0acc4bae4b65784954853f0888572a53fa1a1dc354f97c88ded805f",
96
- "gen-go/types.go": "sha256:bf6906826f4d1c490954cc4354322bf508c392cfc4b72a9a6fe9890f6b5a8d99",
97
- "gen-go/version_state.go": "sha256:827f8768359998409b86ea02d9ba1a149981928bae7161e4dc95fe0520ce7410"
96
+ "gen-go/types.go": "sha256:07642ccb5251d921d801e75b686143ddc23d8e82f03c2f15a175935927a47fc5",
97
+ "gen-go/version_state.go": "sha256:4ef8abb126414c0025cf2c59bc9c79a74ef4a2ff89e8f316cbf05acc872371c1"
98
98
  },
99
99
  "generatedTypeScript": {
100
100
  "gen-ts/ai-budget-ledger-event.ts": "sha256:64448d98a394e6eb103927cd35ce8a33e30176c0d5ee5afcdd8444f8aa051809",
@@ -130,7 +130,7 @@
130
130
  "gen-ts/deployment-source.ts": "sha256:8ccb55aaa7260eb6d19a00987d6a20a4b514e343564da13f27cd7fee8013500a",
131
131
  "gen-ts/deployment-status-failure.ts": "sha256:3ffe268e32240f9da3172b161b8e99e06aa2d21d8c37b30f340506a337c64047",
132
132
  "gen-ts/deployment-status-request.ts": "sha256:7ddccd07ab9f6d0821903a291ab35f903bb055727e03a058b99165ec048f6483",
133
- "gen-ts/deployment-status-response.ts": "sha256:40ec6a03d8b287465007ff35d6abfbae3541a7beea503e02a2ed5aa391f447c2",
133
+ "gen-ts/deployment-status-response.ts": "sha256:1a082b43663b9d7e6f2377c91713bf0792d52060beed5f2bad7879d0ac718bd3",
134
134
  "gen-ts/env-bindings.ts": "sha256:a167cfe9842352c9fec6412ff0d82bda9c5f5c3a1af541bd5c27a57f54fd0941",
135
135
  "gen-ts/error-category-registry.ts": "sha256:280a12aecc8aea8e6e2f2a54d2e968ff7807b522cc0c4036e6e41c065edcf3b7",
136
136
  "gen-ts/error-category.ts": "sha256:9bda89180c3b740c9aa8be466216592e8ca9d0d368c274333edf6ea5c45afd8e",
@@ -142,10 +142,10 @@
142
142
  "gen-ts/sanitized-binding-digest-helper.ts": "sha256:c47d7fdc20500e2e72c23fe39ecdd610fc397c47fcba51335ebec3c380fe6872",
143
143
  "gen-ts/sanitized-binding-evidence.ts": "sha256:4db7e9ed83f563a46e337815a55bbd6433864c41d9ec8e8a80810a16e3095ebb",
144
144
  "gen-ts/secret-reference.ts": "sha256:a8b65de72705b6f51f57cd8ca58881483108005b1fa4d19106c3e9cf1fa877e7",
145
- "gen-ts/security-scan-input.ts": "sha256:5d9bde7394d8b34cca1d36b51ce17bf73cfccd9cfd7cab810f83d4de58f22285",
145
+ "gen-ts/security-scan-input.ts": "sha256:b31f048be04c34b40f49d3b3ba53277e473cd435ae9216ba3a3b4dac69fb5685",
146
146
  "gen-ts/security-verdict.ts": "sha256:fea950cddbd12fe0218e2573c9a29c6748d56612a464559f1e6d688fa97f68c7",
147
147
  "gen-ts/transform-report.ts": "sha256:6c54b579884d98135d73945d00980820b136f269622db27fa56a1c4c0e57d3b6",
148
- "gen-ts/version-state-machine.ts": "sha256:4371bc7e2bde86b0447f5242104c576cc160dfd7dae1885acbfb63540f230bdd",
148
+ "gen-ts/version-state-machine.ts": "sha256:c67af3e86ac306743345b850dfd3ae5201c19d10c40e2c149cf8c38258320d5f",
149
149
  "gen-ts/version-state.ts": "sha256:a835112930299e7b593a1b8810b7414f6c9e809da2092306c743128170a3b702"
150
150
  }
151
151
  }
@@ -1,7 +1,7 @@
1
- export declare const ContractRepositoryVersion: "0.29.0.0";
2
- export declare const ContractPublishVersion: "0.29.0";
3
- export declare const ContractPublishTag: "v0.29.0";
4
- export declare const ContractSchemasDigest: "sha256:4b21ea9a6b13193a189d2499f6cc8f24975db18686e64d2042490a85dca669fc";
1
+ export declare const ContractRepositoryVersion: "0.32.0.0";
2
+ export declare const ContractPublishVersion: "0.32.0";
3
+ export declare const ContractPublishTag: "v0.32.0";
4
+ export declare const ContractSchemasDigest: "sha256:0476a253b6fe583fefeca0766502fbdb4f94987265c86268a489eb6ddfab4d29";
5
5
  export declare const ContractAiFixturesDigest: "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6";
6
- export declare const ContractGeneratedGoDigest: "sha256:6e5af7342005ceb5b2a175b3d5c3eb27e06fe5bfa57e74e2e854038b5f8cbad6";
7
- export declare const ContractGeneratedTypeScriptDigest: "sha256:b6201aeb54e733aaf4f33c2bdf75054b3e10b1616e031620cce15ee72fb37770";
6
+ export declare const ContractGeneratedGoDigest: "sha256:6bb7567f6e0a753136c8389ce8e3a0f8357d360c94ef6f3da3768e63d6562822";
7
+ export declare const ContractGeneratedTypeScriptDigest: "sha256:1f8c32cbe5fbf605bdcaeb73152977a92c488ebd1ab96fb4234a56eb9fc5cee7";
@@ -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.29.0.0";
4
- export const ContractPublishVersion = "0.29.0";
5
- export const ContractPublishTag = "v0.29.0";
6
- export const ContractSchemasDigest = "sha256:4b21ea9a6b13193a189d2499f6cc8f24975db18686e64d2042490a85dca669fc";
3
+ export const ContractRepositoryVersion = "0.32.0.0";
4
+ export const ContractPublishVersion = "0.32.0";
5
+ export const ContractPublishTag = "v0.32.0";
6
+ export const ContractSchemasDigest = "sha256:0476a253b6fe583fefeca0766502fbdb4f94987265c86268a489eb6ddfab4d29";
7
7
  export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6";
8
- export const ContractGeneratedGoDigest = "sha256:6e5af7342005ceb5b2a175b3d5c3eb27e06fe5bfa57e74e2e854038b5f8cbad6";
9
- export const ContractGeneratedTypeScriptDigest = "sha256:b6201aeb54e733aaf4f33c2bdf75054b3e10b1616e031620cce15ee72fb37770";
8
+ export const ContractGeneratedGoDigest = "sha256:6bb7567f6e0a753136c8389ce8e3a0f8357d360c94ef6f3da3768e63d6562822";
9
+ export const ContractGeneratedTypeScriptDigest = "sha256:1f8c32cbe5fbf605bdcaeb73152977a92c488ebd1ab96fb4234a56eb9fc5cee7";
@@ -25,6 +25,7 @@ export interface DeploymentStatusResponse {
25
25
  * @maxItems 50
26
26
  */
27
27
  progress?: StatusProgressEvent[];
28
+ deployTarget?: StatusDeployTarget;
28
29
  }
29
30
  export interface StatusFailureProjection {
30
31
  category: string;
@@ -64,3 +65,16 @@ export interface StatusProgressEvent {
64
65
  remainingMs?: number;
65
66
  origin?: 'initial' | 'widen';
66
67
  }
68
+ /**
69
+ * The customer account and region this version deploys into, stamped on the version record at admission for customer-account (BYOC) tenants. Absent means harbour-managed — the same convention the record itself uses — so every pre-destination version simply omits it. Deliberately only account and region: the record's roleArn/externalId are how the pipeline gets into the account, not where the deploy landed, and no status consumer needs them.
70
+ */
71
+ export interface StatusDeployTarget {
72
+ /**
73
+ * AWS account id the version deploys into.
74
+ */
75
+ account: string;
76
+ /**
77
+ * AWS region the version deploys into, e.g. eu-west-1.
78
+ */
79
+ region: string;
80
+ }
@@ -1,9 +1,9 @@
1
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.
2
+ * Input to the Harbour Security Assurance machine (Security Assurance LLD §2). SOURCE (M1) scans an ingested commit; ARTIFACT (M2) scans built outputs — a container image digest, a deployable bundle, and/or synthesized infrastructure — named directly by the caller. `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. When phase is ARTIFACT at least one of `imageDigest`, `bundleRef`, or `infraRefs` must be present.
3
3
  */
4
4
  export interface SecurityScanInput {
5
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.
6
+ * Scan phase. SOURCE (M1) scans the ingested snapshot for the commit; ARTIFACT (M2) scans built outputs named by imageDigest/bundleRef/infraRefs — at least one of which must be present.
7
7
  */
8
8
  phase: 'SOURCE' | 'ARTIFACT';
9
9
  /**
@@ -34,4 +34,55 @@ export interface SecurityScanInput {
34
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
35
  */
36
36
  classification?: 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED';
37
+ /**
38
+ * ARTIFACT phase: container image to scan, as either a digest-qualified ECR reference (<ecr-uri>@sha256:<64-hex>) or a bare sha256:<64-hex> digest. Digest-addressed only — tags are not accepted, so the scanned bytes are the deployed bytes.
39
+ */
40
+ imageDigest?: string;
41
+ bundleRef?: S3Ref;
42
+ /**
43
+ * ARTIFACT phase: S3 locations of synthesized infrastructure documents (e.g. CloudFormation templates) evaluated by policy (OPA/rego) checks.
44
+ *
45
+ * @minItems 1
46
+ */
47
+ infraRefs?: S3Ref1[];
48
+ /**
49
+ * Optional build-source provenance for ARTIFACT calls where the top-level repo/commit describe the source of the build rather than the artifact itself; stamped into verdict provenance verbatim.
50
+ */
51
+ provenance?: {
52
+ /**
53
+ * GitHub owner/name of the build-source repository.
54
+ */
55
+ repo: string;
56
+ /**
57
+ * Full 40-hex lowercase commit SHA the artifact was built from.
58
+ */
59
+ commit: string;
60
+ /**
61
+ * Branch the artifact was built from, caller-supplied provenance.
62
+ */
63
+ branch?: string;
64
+ };
65
+ }
66
+ /**
67
+ * ARTIFACT phase: S3 location of the built deployable bundle to scan.
68
+ */
69
+ export interface S3Ref {
70
+ /**
71
+ * S3 bucket name.
72
+ */
73
+ bucket: string;
74
+ /**
75
+ * S3 object key.
76
+ */
77
+ key: string;
78
+ }
79
+ export interface S3Ref1 {
80
+ /**
81
+ * S3 bucket name.
82
+ */
83
+ bucket: string;
84
+ /**
85
+ * S3 object key.
86
+ */
87
+ key: string;
37
88
  }
@@ -32,7 +32,8 @@ const legalTransitions = {
32
32
  "PROMOTING": { "LIVE": true, "FAILED": true },
33
33
  },
34
34
  "prod": {
35
- "QUEUED": { "PROMOTING": true, "FAILED": true },
35
+ "QUEUED": { "PROMOTING": true, "GATING": true, "FAILED": true },
36
+ "GATING": { "PROMOTING": true, "FAILED": true, "STALE": true },
36
37
  "PROMOTING": { "LIVE": true, "FAILED": true },
37
38
  },
38
39
  };
@@ -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.29.0.0" as const;
5
- export const ContractPublishVersion = "0.29.0" as const;
6
- export const ContractPublishTag = "v0.29.0" as const;
7
- export const ContractSchemasDigest = "sha256:4b21ea9a6b13193a189d2499f6cc8f24975db18686e64d2042490a85dca669fc" as const;
4
+ export const ContractRepositoryVersion = "0.32.0.0" as const;
5
+ export const ContractPublishVersion = "0.32.0" as const;
6
+ export const ContractPublishTag = "v0.32.0" as const;
7
+ export const ContractSchemasDigest = "sha256:0476a253b6fe583fefeca0766502fbdb4f94987265c86268a489eb6ddfab4d29" as const;
8
8
  export const ContractAiFixturesDigest = "sha256:edac31c92e146ca1c40130f2fb5649db82e24b8cd1ac758153b90612052fddb6" as const;
9
- export const ContractGeneratedGoDigest = "sha256:6e5af7342005ceb5b2a175b3d5c3eb27e06fe5bfa57e74e2e854038b5f8cbad6" as const;
10
- export const ContractGeneratedTypeScriptDigest = "sha256:b6201aeb54e733aaf4f33c2bdf75054b3e10b1616e031620cce15ee72fb37770" as const;
9
+ export const ContractGeneratedGoDigest = "sha256:6bb7567f6e0a753136c8389ce8e3a0f8357d360c94ef6f3da3768e63d6562822" as const;
10
+ export const ContractGeneratedTypeScriptDigest = "sha256:1f8c32cbe5fbf605bdcaeb73152977a92c488ebd1ab96fb4234a56eb9fc5cee7" as const;
@@ -40,6 +40,7 @@ export interface DeploymentStatusResponse {
40
40
  * @maxItems 50
41
41
  */
42
42
  progress?: StatusProgressEvent[];
43
+ deployTarget?: StatusDeployTarget;
43
44
  }
44
45
  export interface StatusFailureProjection {
45
46
  category: string;
@@ -79,3 +80,16 @@ export interface StatusProgressEvent {
79
80
  remainingMs?: number;
80
81
  origin?: 'initial' | 'widen';
81
82
  }
83
+ /**
84
+ * The customer account and region this version deploys into, stamped on the version record at admission for customer-account (BYOC) tenants. Absent means harbour-managed — the same convention the record itself uses — so every pre-destination version simply omits it. Deliberately only account and region: the record's roleArn/externalId are how the pipeline gets into the account, not where the deploy landed, and no status consumer needs them.
85
+ */
86
+ export interface StatusDeployTarget {
87
+ /**
88
+ * AWS account id the version deploys into.
89
+ */
90
+ account: string;
91
+ /**
92
+ * AWS region the version deploys into, e.g. eu-west-1.
93
+ */
94
+ region: string;
95
+ }
@@ -2,11 +2,11 @@
2
2
  // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
3
 
4
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.
5
+ * Input to the Harbour Security Assurance machine (Security Assurance LLD §2). SOURCE (M1) scans an ingested commit; ARTIFACT (M2) scans built outputs — a container image digest, a deployable bundle, and/or synthesized infrastructure — named directly by the caller. `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. When phase is ARTIFACT at least one of `imageDigest`, `bundleRef`, or `infraRefs` must be present.
6
6
  */
7
7
  export interface SecurityScanInput {
8
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.
9
+ * Scan phase. SOURCE (M1) scans the ingested snapshot for the commit; ARTIFACT (M2) scans built outputs named by imageDigest/bundleRef/infraRefs — at least one of which must be present.
10
10
  */
11
11
  phase: 'SOURCE' | 'ARTIFACT';
12
12
  /**
@@ -37,4 +37,55 @@ export interface SecurityScanInput {
37
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
38
  */
39
39
  classification?: 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED';
40
+ /**
41
+ * ARTIFACT phase: container image to scan, as either a digest-qualified ECR reference (<ecr-uri>@sha256:<64-hex>) or a bare sha256:<64-hex> digest. Digest-addressed only — tags are not accepted, so the scanned bytes are the deployed bytes.
42
+ */
43
+ imageDigest?: string;
44
+ bundleRef?: S3Ref;
45
+ /**
46
+ * ARTIFACT phase: S3 locations of synthesized infrastructure documents (e.g. CloudFormation templates) evaluated by policy (OPA/rego) checks.
47
+ *
48
+ * @minItems 1
49
+ */
50
+ infraRefs?: S3Ref1[];
51
+ /**
52
+ * Optional build-source provenance for ARTIFACT calls where the top-level repo/commit describe the source of the build rather than the artifact itself; stamped into verdict provenance verbatim.
53
+ */
54
+ provenance?: {
55
+ /**
56
+ * GitHub owner/name of the build-source repository.
57
+ */
58
+ repo: string;
59
+ /**
60
+ * Full 40-hex lowercase commit SHA the artifact was built from.
61
+ */
62
+ commit: string;
63
+ /**
64
+ * Branch the artifact was built from, caller-supplied provenance.
65
+ */
66
+ branch?: string;
67
+ };
68
+ }
69
+ /**
70
+ * ARTIFACT phase: S3 location of the built deployable bundle to scan.
71
+ */
72
+ export interface S3Ref {
73
+ /**
74
+ * S3 bucket name.
75
+ */
76
+ bucket: string;
77
+ /**
78
+ * S3 object key.
79
+ */
80
+ key: string;
81
+ }
82
+ export interface S3Ref1 {
83
+ /**
84
+ * S3 bucket name.
85
+ */
86
+ bucket: string;
87
+ /**
88
+ * S3 object key.
89
+ */
90
+ key: string;
40
91
  }
@@ -37,7 +37,8 @@ const legalTransitions: Record<string, Record<string, Record<string, true>>> = {
37
37
  "PROMOTING": { "LIVE": true, "FAILED": true },
38
38
  },
39
39
  "prod": {
40
- "QUEUED": { "PROMOTING": true, "FAILED": true },
40
+ "QUEUED": { "PROMOTING": true, "GATING": true, "FAILED": true },
41
+ "GATING": { "PROMOTING": true, "FAILED": true, "STALE": true },
41
42
  "PROMOTING": { "LIVE": true, "FAILED": true },
42
43
  },
43
44
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourier-labs/harbour-contracts",
3
- "version": "0.29.0",
3
+ "version": "0.32.0",
4
4
  "description": "Single source of truth for every data shape that crosses a boundary between Harbour components.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -63,9 +63,31 @@
63
63
  "maxItems": 50,
64
64
  "description": "Bounded chronological trail (oldest first) of human-renderable progress moments observed while this version deployed. Ephemeral and best-effort: a deploy that recorded none — including every deploy that predates this field — simply omits it, so absence means 'no progress view available', never failure.",
65
65
  "items": { "$ref": "#/definitions/StatusProgressEvent" }
66
+ },
67
+ "deployTarget": {
68
+ "$ref": "#/definitions/StatusDeployTarget"
66
69
  }
67
70
  },
68
71
  "definitions": {
72
+ "StatusDeployTarget": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "required": ["account", "region"],
76
+ "description": "The customer account and region this version deploys into, stamped on the version record at admission for customer-account (BYOC) tenants. Absent means harbour-managed — the same convention the record itself uses — so every pre-destination version simply omits it. Deliberately only account and region: the record's roleArn/externalId are how the pipeline gets into the account, not where the deploy landed, and no status consumer needs them.",
77
+ "properties": {
78
+ "account": {
79
+ "type": "string",
80
+ "pattern": "^[0-9]{12}$",
81
+ "description": "AWS account id the version deploys into."
82
+ },
83
+ "region": {
84
+ "type": "string",
85
+ "minLength": 1,
86
+ "maxLength": 32,
87
+ "description": "AWS region the version deploys into, e.g. eu-west-1."
88
+ }
89
+ }
90
+ },
69
91
  "StatusFailureProjection": {
70
92
  "type": "object",
71
93
  "additionalProperties": false,
@@ -2,15 +2,23 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://schemas.harbour.dev/security-scan-input.schema.json",
4
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.",
5
+ "description": "Input to the Harbour Security Assurance machine (Security Assurance LLD §2). SOURCE (M1) scans an ingested commit; ARTIFACT (M2) scans built outputs — a container image digest, a deployable bundle, and/or synthesized infrastructure — named directly by the caller. `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. When phase is ARTIFACT at least one of `imageDigest`, `bundleRef`, or `infraRefs` must be present.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": ["phase", "org", "app", "env", "repo", "commit", "branch"],
9
+ "if": { "properties": { "phase": { "const": "ARTIFACT" } }, "required": ["phase"] },
10
+ "then": {
11
+ "anyOf": [
12
+ { "required": ["imageDigest"] },
13
+ { "required": ["bundleRef"] },
14
+ { "required": ["infraRefs"] }
15
+ ]
16
+ },
9
17
  "properties": {
10
18
  "phase": {
11
19
  "type": "string",
12
20
  "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."
21
+ "description": "Scan phase. SOURCE (M1) scans the ingested snapshot for the commit; ARTIFACT (M2) scans built outputs named by imageDigest/bundleRef/infraRefs — at least one of which must be present."
14
22
  },
15
23
  "org": {
16
24
  "type": "string",
@@ -47,6 +55,56 @@
47
55
  "type": "string",
48
56
  "enum": ["GREEN", "YELLOW", "ORANGE", "RED"],
49
57
  "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."
58
+ },
59
+ "imageDigest": {
60
+ "type": "string",
61
+ "pattern": "^([^@\\s]+@)?sha256:[0-9a-f]{64}$",
62
+ "description": "ARTIFACT phase: container image to scan, as either a digest-qualified ECR reference (<ecr-uri>@sha256:<64-hex>) or a bare sha256:<64-hex> digest. Digest-addressed only — tags are not accepted, so the scanned bytes are the deployed bytes."
63
+ },
64
+ "bundleRef": {
65
+ "$ref": "#/definitions/S3Ref",
66
+ "description": "ARTIFACT phase: S3 location of the built deployable bundle to scan."
67
+ },
68
+ "infraRefs": {
69
+ "type": "array",
70
+ "items": { "$ref": "#/definitions/S3Ref" },
71
+ "minItems": 1,
72
+ "description": "ARTIFACT phase: S3 locations of synthesized infrastructure documents (e.g. CloudFormation templates) evaluated by policy (OPA/rego) checks."
73
+ },
74
+ "provenance": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "required": ["repo", "commit"],
78
+ "properties": {
79
+ "repo": {
80
+ "type": "string",
81
+ "minLength": 1,
82
+ "pattern": "^[^/\\s]+/[^/\\s]+$",
83
+ "description": "GitHub owner/name of the build-source repository."
84
+ },
85
+ "commit": {
86
+ "type": "string",
87
+ "pattern": "^[0-9a-f]{40}$",
88
+ "description": "Full 40-hex lowercase commit SHA the artifact was built from."
89
+ },
90
+ "branch": {
91
+ "type": "string",
92
+ "minLength": 1,
93
+ "description": "Branch the artifact was built from, caller-supplied provenance."
94
+ }
95
+ },
96
+ "description": "Optional build-source provenance for ARTIFACT calls where the top-level repo/commit describe the source of the build rather than the artifact itself; stamped into verdict provenance verbatim."
97
+ }
98
+ },
99
+ "definitions": {
100
+ "S3Ref": {
101
+ "type": "object",
102
+ "additionalProperties": false,
103
+ "required": ["bucket", "key"],
104
+ "properties": {
105
+ "bucket": { "type": "string", "minLength": 1, "description": "S3 bucket name." },
106
+ "key": { "type": "string", "minLength": 1, "description": "S3 object key." }
107
+ }
50
108
  }
51
109
  }
52
110
  }
@@ -36,7 +36,11 @@
36
36
  "x-terminalStable": ["LIVE", "AWAITING-PROMOTION"],
37
37
  "x-transitions": [
38
38
  { "from": "QUEUED", "to": "ANALYZING", "environments": ["preview"], "trigger": "admission: slot free AND commit reachable from branch" },
39
- { "from": "QUEUED", "to": "PROMOTING", "environments": ["prod"], "trigger": "production promotion admission: stored preview and source-fidelity guards pass" },
39
+ { "from": "QUEUED", "to": "PROMOTING", "environments": ["prod"], "trigger": "production promotion admission: stored preview and source-fidelity guards pass (direct path — pipelines not yet opted into security gating)" },
40
+ { "from": "QUEUED", "to": "GATING", "environments": ["prod"], "trigger": "production promotion admission with security gating enabled: guards pass -> evaluate gates before promoting (M3 security assurance, opt-in)" },
41
+ { "from": "GATING", "to": "PROMOTING", "environments": ["prod"], "trigger": "all blocking security gates pass -> proceed to promotion" },
42
+ { "from": "GATING", "to": "FAILED", "environments": ["prod"], "trigger": "a blocking security gate fails; prod alias never moved" },
43
+ { "from": "GATING", "to": "STALE", "environments": ["prod"], "trigger": "newer promotion request passes its guard while gating" },
40
44
  { "from": "QUEUED", "to": "FAILED", "trigger": "admission validation fails — commit not reachable from branch" },
41
45
  { "from": "ANALYZING", "to": "BUILDING", "environments": ["preview"], "trigger": "nothing to transform (fast path)" },
42
46
  { "from": "ANALYZING", "to": "TRANSFORMING", "environments": ["preview"], "trigger": "transform-relevant findings; 15-min wall deadline stamped" },