@xemahq/kernel-contracts 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-workspace/awp-spec.json +1 -1
- package/dist/biome/index.d.ts +5 -0
- package/dist/biome/index.d.ts.map +1 -1
- package/dist/biome/index.js +5 -0
- package/dist/biome/index.js.map +1 -1
- package/dist/biome/lib/biome-audience.d.ts +8 -0
- package/dist/biome/lib/biome-audience.d.ts.map +1 -0
- package/dist/biome/lib/biome-audience.js +12 -0
- package/dist/biome/lib/biome-audience.js.map +1 -0
- package/dist/biome/lib/biome-availability-grant.d.ts +10 -0
- package/dist/biome/lib/biome-availability-grant.d.ts.map +1 -0
- package/dist/biome/lib/biome-availability-grant.js +12 -0
- package/dist/biome/lib/biome-availability-grant.js.map +1 -0
- package/dist/biome/lib/biome-origin.d.ts +8 -0
- package/dist/biome/lib/biome-origin.d.ts.map +1 -0
- package/dist/biome/lib/biome-origin.js +12 -0
- package/dist/biome/lib/biome-origin.js.map +1 -0
- package/dist/biome/lib/biome-target.d.ts +7 -0
- package/dist/biome/lib/biome-target.d.ts.map +1 -0
- package/dist/biome/lib/biome-target.js +11 -0
- package/dist/biome/lib/biome-target.js.map +1 -0
- package/dist/biome/lib/biome-tier.d.ts +10 -0
- package/dist/biome/lib/biome-tier.d.ts.map +1 -0
- package/dist/biome/lib/biome-tier.js +19 -0
- package/dist/biome/lib/biome-tier.js.map +1 -0
- package/dist/contribution/lib/contribution-kind.d.ts +2 -1
- package/dist/contribution/lib/contribution-kind.d.ts.map +1 -1
- package/dist/contribution/lib/contribution-kind.js +1 -0
- package/dist/contribution/lib/contribution-kind.js.map +1 -1
- package/dist/distribution/index.d.ts +5 -0
- package/dist/distribution/index.d.ts.map +1 -0
- package/dist/distribution/index.js +21 -0
- package/dist/distribution/index.js.map +1 -0
- package/dist/distribution/lib/distribution-lock.d.ts +24 -0
- package/dist/distribution/lib/distribution-lock.d.ts.map +1 -0
- package/dist/distribution/lib/distribution-lock.js +34 -0
- package/dist/distribution/lib/distribution-lock.js.map +1 -0
- package/dist/distribution/lib/distribution-selector.d.ts +12 -0
- package/dist/distribution/lib/distribution-selector.d.ts.map +1 -0
- package/dist/distribution/lib/distribution-selector.js +13 -0
- package/dist/distribution/lib/distribution-selector.js.map +1 -0
- package/dist/distribution/lib/distribution.d.ts +21 -0
- package/dist/distribution/lib/distribution.d.ts.map +1 -0
- package/dist/distribution/lib/distribution.js +30 -0
- package/dist/distribution/lib/distribution.js.map +1 -0
- package/dist/distribution/lib/image-lock.d.ts +20 -0
- package/dist/distribution/lib/image-lock.d.ts.map +1 -0
- package/dist/distribution/lib/image-lock.js +30 -0
- package/dist/distribution/lib/image-lock.js.map +1 -0
- package/dist/inquiry/lib/enums.d.ts +4 -0
- package/dist/inquiry/lib/enums.d.ts.map +1 -1
- package/dist/inquiry/lib/enums.js +6 -1
- package/dist/inquiry/lib/enums.js.map +1 -1
- package/dist/inquiry/lib/inquiry.d.ts +5 -9
- package/dist/inquiry/lib/inquiry.d.ts.map +1 -1
- package/dist/inquiry/lib/inquiry.js +4 -2
- package/dist/inquiry/lib/inquiry.js.map +1 -1
- package/dist/invocation/index.d.ts +10 -0
- package/dist/invocation/index.d.ts.map +1 -0
- package/dist/invocation/index.js +26 -0
- package/dist/invocation/index.js.map +1 -0
- package/dist/invocation/lib/execution-requirements.d.ts +24 -0
- package/dist/invocation/lib/execution-requirements.d.ts.map +1 -0
- package/dist/invocation/lib/execution-requirements.js +25 -0
- package/dist/invocation/lib/execution-requirements.js.map +1 -0
- package/dist/invocation/lib/invocation-decision.d.ts +8 -0
- package/dist/invocation/lib/invocation-decision.d.ts.map +1 -0
- package/dist/invocation/lib/invocation-decision.js +10 -0
- package/dist/invocation/lib/invocation-decision.js.map +1 -0
- package/dist/invocation/lib/invocation-mode.d.ts +8 -0
- package/dist/invocation/lib/invocation-mode.d.ts.map +1 -0
- package/dist/invocation/lib/invocation-mode.js +12 -0
- package/dist/invocation/lib/invocation-mode.js.map +1 -0
- package/dist/invocation/lib/invocation-priority.d.ts +8 -0
- package/dist/invocation/lib/invocation-priority.d.ts.map +1 -0
- package/dist/invocation/lib/invocation-priority.js +12 -0
- package/dist/invocation/lib/invocation-priority.js.map +1 -0
- package/dist/invocation/lib/invocation-record.d.ts +27 -0
- package/dist/invocation/lib/invocation-record.d.ts.map +1 -0
- package/dist/invocation/lib/invocation-record.js +29 -0
- package/dist/invocation/lib/invocation-record.js.map +1 -0
- package/dist/invocation/lib/invocation-status.d.ts +13 -0
- package/dist/invocation/lib/invocation-status.d.ts.map +1 -0
- package/dist/invocation/lib/invocation-status.js +17 -0
- package/dist/invocation/lib/invocation-status.js.map +1 -0
- package/dist/invocation/lib/invoke-request.d.ts +13 -0
- package/dist/invocation/lib/invoke-request.d.ts.map +1 -0
- package/dist/invocation/lib/invoke-request.js +15 -0
- package/dist/invocation/lib/invoke-request.js.map +1 -0
- package/dist/invocation/lib/invoke-response.d.ts +17 -0
- package/dist/invocation/lib/invoke-response.d.ts.map +1 -0
- package/dist/invocation/lib/invoke-response.js +19 -0
- package/dist/invocation/lib/invoke-response.js.map +1 -0
- package/dist/invocation/lib/isolation-level.d.ts +7 -0
- package/dist/invocation/lib/isolation-level.d.ts.map +1 -0
- package/dist/invocation/lib/isolation-level.js +11 -0
- package/dist/invocation/lib/isolation-level.js.map +1 -0
- package/dist/mail-source/index.d.ts +2 -0
- package/dist/mail-source/index.d.ts.map +1 -0
- package/dist/mail-source/index.js +18 -0
- package/dist/mail-source/index.js.map +1 -0
- package/dist/mail-source/lib/mail-event.d.ts +58 -0
- package/dist/mail-source/lib/mail-event.d.ts.map +1 -0
- package/dist/mail-source/lib/mail-event.js +41 -0
- package/dist/mail-source/lib/mail-event.js.map +1 -0
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +1 -0
- package/dist/policy/index.js.map +1 -1
- package/dist/policy/lib/egress-allowlist.d.ts +18 -0
- package/dist/policy/lib/egress-allowlist.d.ts.map +1 -0
- package/dist/policy/lib/egress-allowlist.js +130 -0
- package/dist/policy/lib/egress-allowlist.js.map +1 -0
- package/dist/policy/lib/obligations.d.ts +12 -1
- package/dist/policy/lib/obligations.d.ts.map +1 -1
- package/dist/policy/lib/obligations.js +14 -1
- package/dist/policy/lib/obligations.js.map +1 -1
- package/package.json +1 -1
- package/src/biome/index.ts +5 -0
- package/src/biome/lib/biome-audience.ts +27 -0
- package/src/biome/lib/biome-availability-grant.ts +42 -0
- package/src/biome/lib/biome-origin.ts +26 -0
- package/src/biome/lib/biome-target.ts +16 -0
- package/src/biome/lib/biome-tier.ts +44 -0
- package/src/contribution/lib/contribution-kind.ts +14 -0
- package/src/distribution/index.ts +4 -0
- package/src/distribution/lib/distribution-lock.ts +88 -0
- package/src/distribution/lib/distribution-selector.ts +35 -0
- package/src/distribution/lib/distribution.ts +82 -0
- package/src/distribution/lib/image-lock.ts +77 -0
- package/src/inquiry/lib/enums.ts +13 -0
- package/src/inquiry/lib/inquiry.ts +22 -4
- package/src/invocation/index.ts +9 -0
- package/src/invocation/lib/execution-requirements.ts +61 -0
- package/src/invocation/lib/invocation-decision.ts +21 -0
- package/src/invocation/lib/invocation-mode.ts +26 -0
- package/src/invocation/lib/invocation-priority.ts +16 -0
- package/src/invocation/lib/invocation-record.ts +59 -0
- package/src/invocation/lib/invocation-status.ts +32 -0
- package/src/invocation/lib/invoke-request.ts +34 -0
- package/src/invocation/lib/invoke-response.ts +39 -0
- package/src/invocation/lib/isolation-level.ts +20 -0
- package/src/mail-source/index.ts +1 -0
- package/src/mail-source/lib/mail-event.ts +106 -0
- package/src/policy/index.ts +1 -0
- package/src/policy/lib/egress-allowlist.ts +239 -0
- package/src/policy/lib/obligations.ts +61 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAIL_EVENT_DATA_TYPE = exports.MAIL_EVENT_SOURCE = exports.MAIL_EVENT_SCHEMA_VERSION = exports.MailThreadUpdatedSchema = exports.MailMessageClassifiedSchema = exports.MailMessageReceivedSchema = exports.MailEventBaseSchema = exports.MailEventType = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
var MailEventType;
|
|
6
|
+
(function (MailEventType) {
|
|
7
|
+
MailEventType["MessageReceived"] = "mail.message.received";
|
|
8
|
+
MailEventType["MessageClassified"] = "mail.message.classified";
|
|
9
|
+
MailEventType["ThreadUpdated"] = "mail.thread.updated";
|
|
10
|
+
})(MailEventType || (exports.MailEventType = MailEventType = {}));
|
|
11
|
+
exports.MailEventBaseSchema = zod_1.z.object({
|
|
12
|
+
orgId: zod_1.z.string().min(1),
|
|
13
|
+
projectId: zod_1.z.string().min(1).optional(),
|
|
14
|
+
mailboxRef: zod_1.z.string().min(1),
|
|
15
|
+
messageId: zod_1.z.string().min(1),
|
|
16
|
+
threadRef: zod_1.z.string().min(1).optional(),
|
|
17
|
+
from: zod_1.z.string().min(1),
|
|
18
|
+
subject: zod_1.z.string().optional(),
|
|
19
|
+
receivedAt: zod_1.z.string().min(1),
|
|
20
|
+
labels: zod_1.z.array(zod_1.z.string()).optional(),
|
|
21
|
+
});
|
|
22
|
+
exports.MailMessageReceivedSchema = exports.MailEventBaseSchema.extend({
|
|
23
|
+
classification: zod_1.z.string().min(1).optional(),
|
|
24
|
+
});
|
|
25
|
+
exports.MailMessageClassifiedSchema = exports.MailEventBaseSchema.extend({
|
|
26
|
+
classification: zod_1.z.string().min(1),
|
|
27
|
+
});
|
|
28
|
+
exports.MailThreadUpdatedSchema = zod_1.z.object({
|
|
29
|
+
orgId: zod_1.z.string().min(1),
|
|
30
|
+
projectId: zod_1.z.string().min(1).optional(),
|
|
31
|
+
mailboxRef: zod_1.z.string().min(1),
|
|
32
|
+
threadRef: zod_1.z.string().min(1),
|
|
33
|
+
subject: zod_1.z.string().optional(),
|
|
34
|
+
participants: zod_1.z.array(zod_1.z.string()),
|
|
35
|
+
messageCount: zod_1.z.number().int().nonnegative(),
|
|
36
|
+
lastReceivedAt: zod_1.z.string().min(1),
|
|
37
|
+
});
|
|
38
|
+
exports.MAIL_EVENT_SCHEMA_VERSION = '1.0.0';
|
|
39
|
+
exports.MAIL_EVENT_SOURCE = '/xema/services/mailops-api';
|
|
40
|
+
exports.MAIL_EVENT_DATA_TYPE = 'mailops';
|
|
41
|
+
//# sourceMappingURL=mail-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mail-event.js","sourceRoot":"","sources":["../../../src/mail-source/lib/mail-event.ts"],"names":[],"mappings":";;;AAsBA,6BAAwB;AAMxB,IAAY,aAOX;AAPD,WAAY,aAAa;IAEvB,0DAAyC,CAAA;IAEzC,8DAA6C,CAAA;IAE7C,sDAAqC,CAAA;AACvC,CAAC,EAPW,aAAa,6BAAb,aAAa,QAOxB;AAMY,QAAA,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAEvC,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7B,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5B,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE9B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7B,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAGU,QAAA,yBAAyB,GAAG,2BAAmB,CAAC,MAAM,CAAC;IAKlE,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;AAMU,QAAA,2BAA2B,GAAG,2BAAmB,CAAC,MAAM,CAAC;IACpE,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAClC,CAAC,CAAC;AAGU,QAAA,uBAAuB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC9C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE9B,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;IAEjC,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAE5C,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAClC,CAAC,CAAC;AAWU,QAAA,yBAAyB,GAAG,OAAgB,CAAC;AAG7C,QAAA,iBAAiB,GAAG,4BAAqC,CAAC;AAG1D,QAAA,oBAAoB,GAAG,SAAkB,CAAC"}
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
|
package/dist/policy/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./lib/obligations"), exports);
|
|
18
|
+
__exportStar(require("./lib/egress-allowlist"), exports);
|
|
18
19
|
__exportStar(require("./lib/route-hints"), exports);
|
|
19
20
|
__exportStar(require("./lib/policy"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
package/dist/policy/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,oDAAkC;AAClC,+CAA6B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC;AACvC,oDAAkC;AAClC,+CAA6B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type EgressAllowlistObligation } from './obligations';
|
|
2
|
+
export type EgressDecision = {
|
|
3
|
+
readonly allowed: true;
|
|
4
|
+
} | {
|
|
5
|
+
readonly allowed: false;
|
|
6
|
+
readonly reason: EgressDenyReason;
|
|
7
|
+
};
|
|
8
|
+
export declare enum EgressDenyReason {
|
|
9
|
+
InvalidTarget = "invalid-target",
|
|
10
|
+
Blocklisted = "blocklisted",
|
|
11
|
+
NotAllowlisted = "not-allowlisted"
|
|
12
|
+
}
|
|
13
|
+
export declare class MalformedEgressObligationError extends Error {
|
|
14
|
+
constructor(detail: string);
|
|
15
|
+
}
|
|
16
|
+
export declare function evaluateEgress(targetUrl: string, obligation: EgressAllowlistObligation): EgressDecision;
|
|
17
|
+
export declare function isEgressAllowed(targetUrl: string, obligation: EgressAllowlistObligation): boolean;
|
|
18
|
+
//# sourceMappingURL=egress-allowlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress-allowlist.d.ts","sourceRoot":"","sources":["../../../src/policy/lib/egress-allowlist.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,eAAe,CAAC;AAmBvB,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAGnE,oBAAY,gBAAgB;IAE1B,aAAa,mBAAmB;IAEhC,WAAW,gBAAgB;IAE3B,cAAc,oBAAoB;CACnC;AAOD,qBAAa,8BAA+B,SAAQ,KAAK;gBAC3C,MAAM,EAAE,MAAM;CAI3B;AAcD,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,yBAAyB,GACpC,cAAc,CA6BhB;AAOD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,yBAAyB,GACpC,OAAO,CAET"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MalformedEgressObligationError = exports.EgressDenyReason = void 0;
|
|
4
|
+
exports.evaluateEgress = evaluateEgress;
|
|
5
|
+
exports.isEgressAllowed = isEgressAllowed;
|
|
6
|
+
const obligations_1 = require("./obligations");
|
|
7
|
+
var EgressDenyReason;
|
|
8
|
+
(function (EgressDenyReason) {
|
|
9
|
+
EgressDenyReason["InvalidTarget"] = "invalid-target";
|
|
10
|
+
EgressDenyReason["Blocklisted"] = "blocklisted";
|
|
11
|
+
EgressDenyReason["NotAllowlisted"] = "not-allowlisted";
|
|
12
|
+
})(EgressDenyReason || (exports.EgressDenyReason = EgressDenyReason = {}));
|
|
13
|
+
class MalformedEgressObligationError extends Error {
|
|
14
|
+
constructor(detail) {
|
|
15
|
+
super(`Malformed egress-allowlist obligation: ${detail}`);
|
|
16
|
+
this.name = 'MalformedEgressObligationError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.MalformedEgressObligationError = MalformedEgressObligationError;
|
|
20
|
+
function evaluateEgress(targetUrl, obligation) {
|
|
21
|
+
const parsed = obligations_1.EgressAllowlistObligationSchema.safeParse(obligation);
|
|
22
|
+
if (!parsed.success) {
|
|
23
|
+
throw new MalformedEgressObligationError(parsed.error.issues[0]?.message ?? 'invalid payload');
|
|
24
|
+
}
|
|
25
|
+
const { allow, deny } = parsed.data;
|
|
26
|
+
const target = parseTarget(targetUrl);
|
|
27
|
+
if (target === null) {
|
|
28
|
+
return { allowed: false, reason: EgressDenyReason.InvalidTarget };
|
|
29
|
+
}
|
|
30
|
+
if (deny !== undefined) {
|
|
31
|
+
for (const pattern of deny) {
|
|
32
|
+
if (matchPattern(pattern, target)) {
|
|
33
|
+
return { allowed: false, reason: EgressDenyReason.Blocklisted };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const pattern of allow) {
|
|
38
|
+
if (matchPattern(pattern, target)) {
|
|
39
|
+
return { allowed: true };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { allowed: false, reason: EgressDenyReason.NotAllowlisted };
|
|
43
|
+
}
|
|
44
|
+
function isEgressAllowed(targetUrl, obligation) {
|
|
45
|
+
return evaluateEgress(targetUrl, obligation).allowed;
|
|
46
|
+
}
|
|
47
|
+
function parseTarget(rawUrl) {
|
|
48
|
+
let u;
|
|
49
|
+
try {
|
|
50
|
+
u = new URL(rawUrl);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (u.protocol !== 'http:' && u.protocol !== 'https:') {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const host = u.hostname.toLowerCase().replace(/\.$/, '');
|
|
59
|
+
if (host.length === 0) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return { host, scheme: u.protocol, path: normalisePath(u.pathname) };
|
|
63
|
+
}
|
|
64
|
+
function normalisePath(pathname) {
|
|
65
|
+
const collapsed = pathname.replace(/\/{2,}/g, '/');
|
|
66
|
+
if (collapsed.length > 1 && collapsed.endsWith('/')) {
|
|
67
|
+
return collapsed.slice(0, -1);
|
|
68
|
+
}
|
|
69
|
+
return collapsed.length === 0 ? '/' : collapsed;
|
|
70
|
+
}
|
|
71
|
+
function matchPattern(pattern, target) {
|
|
72
|
+
const schemeSep = pattern.indexOf('://');
|
|
73
|
+
if (schemeSep === -1) {
|
|
74
|
+
if (pattern.includes('/')) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return matchHost(pattern.toLowerCase(), target.host);
|
|
78
|
+
}
|
|
79
|
+
const scheme = pattern.slice(0, schemeSep + 1).toLowerCase();
|
|
80
|
+
if (scheme !== target.scheme) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const rest = pattern.slice(schemeSep + 3);
|
|
84
|
+
const slash = rest.indexOf('/');
|
|
85
|
+
const hostPart = (slash === -1 ? rest : rest.slice(0, slash)).toLowerCase();
|
|
86
|
+
const pathPart = slash === -1 ? '' : rest.slice(slash);
|
|
87
|
+
if (!matchHost(hostPart, target.host)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return matchPath(pathPart, target.path);
|
|
91
|
+
}
|
|
92
|
+
function matchHost(pattern, host) {
|
|
93
|
+
if (pattern.length === 0) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const pLabels = pattern.split('.');
|
|
97
|
+
const hLabels = host.split('.');
|
|
98
|
+
if (pLabels.length !== hLabels.length) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
for (let i = 0; i < pLabels.length; i++) {
|
|
102
|
+
const pl = pLabels[i];
|
|
103
|
+
const hl = hLabels[i];
|
|
104
|
+
if (pl === '*') {
|
|
105
|
+
if (hl === undefined || hl.length === 0) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (pl !== hl) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
function matchPath(patternPath, targetPath) {
|
|
117
|
+
if (patternPath === '' || patternPath === '/') {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const wildcard = patternPath.endsWith('/*');
|
|
121
|
+
const base = normalisePath(wildcard ? patternPath.slice(0, -2) : patternPath);
|
|
122
|
+
if (!wildcard) {
|
|
123
|
+
return targetPath === base;
|
|
124
|
+
}
|
|
125
|
+
if (targetPath === base) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return targetPath.startsWith(base === '/' ? '/' : `${base}/`);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=egress-allowlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress-allowlist.js","sourceRoot":"","sources":["../../../src/policy/lib/egress-allowlist.ts"],"names":[],"mappings":";;;AA4DA,wCAgCC;AAOD,0CAKC;AAxGD,+CAGuB;AAwBvB,IAAY,gBAOX;AAPD,WAAY,gBAAgB;IAE1B,oDAAgC,CAAA;IAEhC,+CAA2B,CAAA;IAE3B,sDAAkC,CAAA;AACpC,CAAC,EAPW,gBAAgB,gCAAhB,gBAAgB,QAO3B;AAOD,MAAa,8BAA+B,SAAQ,KAAK;IACvD,YAAY,MAAc;QACxB,KAAK,CAAC,0CAA0C,MAAM,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,GAAG,gCAAgC,CAAC;IAC/C,CAAC;CACF;AALD,wEAKC;AAcD,SAAgB,cAAc,CAC5B,SAAiB,EACjB,UAAqC;IAKrC,MAAM,MAAM,GAAG,6CAA+B,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,8BAA8B,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,iBAAiB,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,aAAa,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;YAC3B,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,cAAc,EAAE,CAAC;AACrE,CAAC;AAOD,SAAgB,eAAe,CAC7B,SAAiB,EACjB,UAAqC;IAErC,OAAO,cAAc,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC;AACvD,CAAC;AAsBD,SAAS,WAAW,CAAC,MAAc;IACjC,IAAI,CAAM,CAAC;IACX,IAAI,CAAC;QACH,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvE,CAAC;AAGD,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACnD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AAOD,SAAS,YAAY,CAAC,OAAe,EAAE,MAAoB;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QAErB,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAI1B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7D,IAAI,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAOD,SAAS,SAAS,CAAC,OAAe,EAAE,IAAY;IAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAEf,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACd,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAUD,SAAS,SAAS,CAAC,WAAmB,EAAE,UAAkB;IACxD,IAAI,WAAW,KAAK,EAAE,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC9E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,UAAU,KAAK,IAAI,CAAC;IAC7B,CAAC;IAGD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -7,7 +7,8 @@ export declare enum PolicyObligationKind {
|
|
|
7
7
|
MaxDurationSeconds = "max-duration-seconds",
|
|
8
8
|
MaxCostUsd = "max-cost-usd",
|
|
9
9
|
RestrictOutputClassification = "restrict-output-classification",
|
|
10
|
-
DataResidency = "data-residency"
|
|
10
|
+
DataResidency = "data-residency",
|
|
11
|
+
EgressAllowlist = "egress-allowlist"
|
|
11
12
|
}
|
|
12
13
|
export declare const PolicyObligationKindSchema: z.ZodEnum<typeof PolicyObligationKind>;
|
|
13
14
|
export declare enum RunnerKind {
|
|
@@ -64,6 +65,12 @@ export declare const DataResidencyObligationSchema: z.ZodObject<{
|
|
|
64
65
|
residency: z.ZodEnum<typeof DataResidency>;
|
|
65
66
|
}, z.core.$strip>;
|
|
66
67
|
export type DataResidencyObligation = z.infer<typeof DataResidencyObligationSchema>;
|
|
68
|
+
export declare const EgressAllowlistObligationSchema: z.ZodObject<{
|
|
69
|
+
kind: z.ZodLiteral<PolicyObligationKind.EgressAllowlist>;
|
|
70
|
+
allow: z.ZodArray<z.ZodString>;
|
|
71
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
export type EgressAllowlistObligation = z.infer<typeof EgressAllowlistObligationSchema>;
|
|
67
74
|
export declare const PolicyObligationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
68
75
|
kind: z.ZodLiteral<PolicyObligationKind.Audit>;
|
|
69
76
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -86,6 +93,10 @@ export declare const PolicyObligationSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
86
93
|
}, z.core.$strip>, z.ZodObject<{
|
|
87
94
|
kind: z.ZodLiteral<PolicyObligationKind.DataResidency>;
|
|
88
95
|
residency: z.ZodEnum<typeof DataResidency>;
|
|
96
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
97
|
+
kind: z.ZodLiteral<PolicyObligationKind.EgressAllowlist>;
|
|
98
|
+
allow: z.ZodArray<z.ZodString>;
|
|
99
|
+
deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
89
100
|
}, z.core.$strip>], "kind">;
|
|
90
101
|
export type PolicyObligation = z.infer<typeof PolicyObligationSchema>;
|
|
91
102
|
//# sourceMappingURL=obligations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../../src/policy/lib/obligations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,oBAAY,oBAAoB;IAC9B,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,iBAAiB,wBAAwB;IACzC,oBAAoB,2BAA2B;IAC/C,kBAAkB,yBAAyB;IAC3C,UAAU,iBAAiB;IAC3B,4BAA4B,mCAAmC;IAC/D,aAAa,mBAAmB;
|
|
1
|
+
{"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../../src/policy/lib/obligations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,oBAAY,oBAAoB;IAC9B,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,iBAAiB,wBAAwB;IACzC,oBAAoB,2BAA2B;IAC/C,kBAAkB,yBAAyB;IAC3C,UAAU,iBAAiB;IAC3B,4BAA4B,mCAAmC;IAC/D,aAAa,mBAAmB;IAShC,eAAe,qBAAqB;CACrC;AAED,eAAO,MAAM,0BAA0B,wCAAqC,CAAC;AAa7E,oBAAY,UAAU;IACpB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,YAAY,kBAAkB;IAC9B,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,EAAE,OAAO;IAQT,WAAW,iBAAiB;CAC7B;AAED,eAAO,MAAM,gBAAgB,8BAA2B,CAAC;AAWzD,oBAAY,aAAa;IACvB,EAAE,OAAO;IACT,EAAE,OAAO;IACT,eAAe,qBAAqB;CACrC;AAED,eAAO,MAAM,mBAAmB,iCAA8B,CAAC;AAU/D,eAAO,MAAM,qBAAqB;;iBAEhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,6BAA6B;;iBAExC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,iCAAiC;;;iBAG5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,iCAAiC,CACzC,CAAC;AAEF,eAAO,MAAM,oCAAoC;;;iBAI/C,CAAC;AACH,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAClD,OAAO,oCAAoC,CAC5C,CAAC;AAEF,eAAO,MAAM,kCAAkC;;;iBAG7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAChD,OAAO,kCAAkC,CAC1C,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;iBAGrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,4CAA4C;;;iBAGvD,CAAC;AACH,MAAM,MAAM,sCAAsC,GAAG,CAAC,CAAC,KAAK,CAC1D,OAAO,4CAA4C,CACpD,CAAC;AAEF,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AAoCF,eAAO,MAAM,+BAA+B;;;;iBAY1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC;AASF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;2BAUjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PolicyObligationSchema = exports.DataResidencyObligationSchema = exports.RestrictOutputClassificationObligationSchema = exports.MaxCostUsdObligationSchema = exports.MaxDurationSecondsObligationSchema = exports.RequireHumanApprovalObligationSchema = exports.RequireRunnerKindObligationSchema = exports.RedactSecretsObligationSchema = exports.AuditObligationSchema = exports.DataResidencySchema = exports.DataResidency = exports.RunnerKindSchema = exports.RunnerKind = exports.PolicyObligationKindSchema = exports.PolicyObligationKind = void 0;
|
|
3
|
+
exports.PolicyObligationSchema = exports.EgressAllowlistObligationSchema = exports.DataResidencyObligationSchema = exports.RestrictOutputClassificationObligationSchema = exports.MaxCostUsdObligationSchema = exports.MaxDurationSecondsObligationSchema = exports.RequireHumanApprovalObligationSchema = exports.RequireRunnerKindObligationSchema = exports.RedactSecretsObligationSchema = exports.AuditObligationSchema = exports.DataResidencySchema = exports.DataResidency = exports.RunnerKindSchema = exports.RunnerKind = exports.PolicyObligationKindSchema = exports.PolicyObligationKind = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const space_1 = require("../../space");
|
|
6
6
|
var PolicyObligationKind;
|
|
@@ -13,6 +13,7 @@ var PolicyObligationKind;
|
|
|
13
13
|
PolicyObligationKind["MaxCostUsd"] = "max-cost-usd";
|
|
14
14
|
PolicyObligationKind["RestrictOutputClassification"] = "restrict-output-classification";
|
|
15
15
|
PolicyObligationKind["DataResidency"] = "data-residency";
|
|
16
|
+
PolicyObligationKind["EgressAllowlist"] = "egress-allowlist";
|
|
16
17
|
})(PolicyObligationKind || (exports.PolicyObligationKind = PolicyObligationKind = {}));
|
|
17
18
|
exports.PolicyObligationKindSchema = zod_1.z.nativeEnum(PolicyObligationKind);
|
|
18
19
|
var RunnerKind;
|
|
@@ -63,6 +64,17 @@ exports.DataResidencyObligationSchema = zod_1.z.object({
|
|
|
63
64
|
kind: zod_1.z.literal(PolicyObligationKind.DataResidency),
|
|
64
65
|
residency: exports.DataResidencySchema,
|
|
65
66
|
});
|
|
67
|
+
const EGRESS_PATTERN = zod_1.z
|
|
68
|
+
.string()
|
|
69
|
+
.min(1)
|
|
70
|
+
.refine((p) => !/[\s@#?]/.test(p), {
|
|
71
|
+
message: 'egress pattern must not contain whitespace, "@", "#" or "?" (those belong to the target URL, not the rule)',
|
|
72
|
+
});
|
|
73
|
+
exports.EgressAllowlistObligationSchema = zod_1.z.object({
|
|
74
|
+
kind: zod_1.z.literal(PolicyObligationKind.EgressAllowlist),
|
|
75
|
+
allow: zod_1.z.array(EGRESS_PATTERN).min(1),
|
|
76
|
+
deny: zod_1.z.array(EGRESS_PATTERN).optional(),
|
|
77
|
+
});
|
|
66
78
|
exports.PolicyObligationSchema = zod_1.z.discriminatedUnion('kind', [
|
|
67
79
|
exports.AuditObligationSchema,
|
|
68
80
|
exports.RedactSecretsObligationSchema,
|
|
@@ -72,5 +84,6 @@ exports.PolicyObligationSchema = zod_1.z.discriminatedUnion('kind', [
|
|
|
72
84
|
exports.MaxCostUsdObligationSchema,
|
|
73
85
|
exports.RestrictOutputClassificationObligationSchema,
|
|
74
86
|
exports.DataResidencyObligationSchema,
|
|
87
|
+
exports.EgressAllowlistObligationSchema,
|
|
75
88
|
]);
|
|
76
89
|
//# sourceMappingURL=obligations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obligations.js","sourceRoot":"","sources":["../../../src/policy/lib/obligations.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,uCAAuD;AAUvD,IAAY,
|
|
1
|
+
{"version":3,"file":"obligations.js","sourceRoot":"","sources":["../../../src/policy/lib/obligations.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,uCAAuD;AAUvD,IAAY,oBAkBX;AAlBD,WAAY,oBAAoB;IAC9B,uCAAe,CAAA;IACf,wDAAgC,CAAA;IAChC,iEAAyC,CAAA;IACzC,uEAA+C,CAAA;IAC/C,mEAA2C,CAAA;IAC3C,mDAA2B,CAAA;IAC3B,uFAA+D,CAAA;IAC/D,wDAAgC,CAAA;IAShC,4DAAoC,CAAA;AACtC,CAAC,EAlBW,oBAAoB,oCAApB,oBAAoB,QAkB/B;AAEY,QAAA,0BAA0B,GAAG,OAAC,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AAa7E,IAAY,UAeX;AAfD,WAAY,UAAU;IACpB,6BAAe,CAAA;IACf,6BAAe,CAAA;IACf,4CAA8B,CAAA;IAC9B,yBAAW,CAAA;IACX,iCAAmB,CAAA;IACnB,uBAAS,CAAA;IAQT,0CAA4B,CAAA;AAC9B,CAAC,EAfW,UAAU,0BAAV,UAAU,QAerB;AAEY,QAAA,gBAAgB,GAAG,OAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAWzD,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,0BAAS,CAAA;IACT,0BAAS,CAAA;IACT,qDAAoC,CAAA;AACtC,CAAC,EAJW,aAAa,6BAAb,aAAa,QAIxB;AAEY,QAAA,mBAAmB,GAAG,OAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAUlD,QAAA,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC;CAC5C,CAAC,CAAC;AAGU,QAAA,6BAA6B,GAAG,OAAC,CAAC,MAAM,CAAC;IACpD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,aAAa,CAAC;CACpD,CAAC,CAAC;AAGU,QAAA,iCAAiC,GAAG,OAAC,CAAC,MAAM,CAAC;IACxD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACvD,UAAU,EAAE,wBAAgB;CAC7B,CAAC,CAAC;AAKU,QAAA,oCAAoC,GAAG,OAAC,CAAC,MAAM,CAAC;IAC3D,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,oBAAoB,CAAC;IAE1D,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAKU,QAAA,kCAAkC,GAAG,OAAC,CAAC,MAAM,CAAC;IACzD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,kBAAkB,CAAC;IACxD,kBAAkB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAKU,QAAA,0BAA0B,GAAG,OAAC,CAAC,MAAM,CAAC;IACjD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,UAAU,CAAC;IAChD,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAGU,QAAA,4CAA4C,GAAG,OAAC,CAAC,MAAM,CAAC;IACnE,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,4BAA4B,CAAC;IAClE,iBAAiB,EAAE,gCAAwB;CAC5C,CAAC,CAAC;AAKU,QAAA,6BAA6B,GAAG,OAAC,CAAC,MAAM,CAAC;IACpD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,aAAa,CAAC;IACnD,SAAS,EAAE,2BAAmB;CAC/B,CAAC,CAAC;AA4BH,MAAM,cAAc,GAAG,OAAC;KACrB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KAIN,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;IACjC,OAAO,EACL,4GAA4G;CAC/G,CAAC,CAAC;AAEQ,QAAA,+BAA+B,GAAG,OAAC,CAAC,MAAM,CAAC;IACtD,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,eAAe,CAAC;IAQrD,KAAK,EAAE,OAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAErC,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAC;AAYU,QAAA,sBAAsB,GAAG,OAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACjE,6BAAqB;IACrB,qCAA6B;IAC7B,yCAAiC;IACjC,4CAAoC;IACpC,0CAAkC;IAClC,kCAA0B;IAC1B,oDAA4C;IAC5C,qCAA6B;IAC7B,uCAA+B;CAChC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/kernel-contracts",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Consolidated Xema OS kernel wire contracts — pure types + zod schemas for the 32 kernel protocol surfaces. One package, one npm scope, wildcard per-surface subpath exports. No framework/runtime deps.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
package/src/biome/index.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export * from './lib/biome-capability-refs';
|
|
2
2
|
export * from './lib/biome-lifecycle';
|
|
3
3
|
export * from './lib/biome-scope';
|
|
4
|
+
export * from './lib/biome-tier';
|
|
5
|
+
export * from './lib/biome-target';
|
|
6
|
+
export * from './lib/biome-audience';
|
|
7
|
+
export * from './lib/biome-origin';
|
|
4
8
|
export * from './lib/biome-trust-tier';
|
|
9
|
+
export * from './lib/biome-availability-grant';
|
|
5
10
|
export * from './lib/biome-api';
|
|
6
11
|
export * from './lib/biome-lifecycle-hooks';
|
|
7
12
|
export * from './lib/biome-engines';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `BiomeAudience` — WHO a biome is for. Orthogonal to dependency tier
|
|
5
|
+
* (`BiomeTier`), origin (`BiomeOrigin`), and install scope (`BiomeScope`).
|
|
6
|
+
*
|
|
7
|
+
* - `Org` (default) — a normal biome, available to organizations (subject to
|
|
8
|
+
* org enablement + availability grants) and eligible to appear in the store.
|
|
9
|
+
* - `Operator` — for Xema PLATFORM OPERATORS only (us). Effects, enforced
|
|
10
|
+
* across the planes:
|
|
11
|
+
* 1. Packaging — distribution SELECTORS skip operator biomes; they ship
|
|
12
|
+
* only when explicitly named in `include[]` (the "force it in" rule for
|
|
13
|
+
* the internal distribution).
|
|
14
|
+
* 2. Discovery — never store-listed; hidden from org-facing biome UIs.
|
|
15
|
+
* 3. Access — gated to the `platform_admin` realm role.
|
|
16
|
+
*
|
|
17
|
+
* Closed set; new values are a kernel change.
|
|
18
|
+
*/
|
|
19
|
+
export enum BiomeAudience {
|
|
20
|
+
Org = 'org',
|
|
21
|
+
Operator = 'operator',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const BiomeAudienceSchema = z.nativeEnum(BiomeAudience);
|
|
25
|
+
|
|
26
|
+
/** The default audience applied when a manifest omits the field. */
|
|
27
|
+
export const DEFAULT_BIOME_AUDIENCE = BiomeAudience.Org;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SubjectRefSchema, type SubjectRef } from '../../subject';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Canonical authorization action for "may this subject see/use this biome".
|
|
6
|
+
* Registered as a gatable action in `authorization-api`; the biome-host web
|
|
7
|
+
* registry filters the per-org biome list by evaluating this action for the
|
|
8
|
+
* caller. NOT the same as installing or enabling a biome (those are org-admin
|
|
9
|
+
* actions) — this is the third, finer level: availability to a subject within
|
|
10
|
+
* an org that has already enabled the biome.
|
|
11
|
+
*/
|
|
12
|
+
export const BIOME_ACCESS_ACTION = 'biome.access';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `BiomeAvailabilityGrant` — makes an org-enabled biome available to a specific
|
|
16
|
+
* subject (a `user` or a `group`/team) within an org.
|
|
17
|
+
*
|
|
18
|
+
* Semantics (fail-OPEN by absence, NOT by error):
|
|
19
|
+
* - If an org has ZERO grant rows for a biome, the biome is available
|
|
20
|
+
* ORG-WIDE (the default; preserves today's org-wide enablement behaviour).
|
|
21
|
+
* - If an org has ONE OR MORE grant rows for a biome, the biome is available
|
|
22
|
+
* ONLY to the union of the granted subjects (and to org/platform admins).
|
|
23
|
+
*
|
|
24
|
+
* `subject.kind` is meaningful only for `User` and `Group` (team). Org-wide
|
|
25
|
+
* availability is expressed by the ABSENCE of rows, never by an `org` subject
|
|
26
|
+
* row — so there is exactly one way to say "everyone".
|
|
27
|
+
*
|
|
28
|
+
* Backed by `authorization-api` (the PDP) as grants over the `biome.access`
|
|
29
|
+
* action; the biome-id is the resource. Portals are the UI that writes these
|
|
30
|
+
* rows — availability is the generic permission, Portals are the curation lens.
|
|
31
|
+
*/
|
|
32
|
+
export interface BiomeAvailabilityGrant {
|
|
33
|
+
orgId: string;
|
|
34
|
+
biomeId: string;
|
|
35
|
+
subject: SubjectRef;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const BiomeAvailabilityGrantSchema = z.object({
|
|
39
|
+
orgId: z.string().min(1),
|
|
40
|
+
biomeId: z.string().min(1),
|
|
41
|
+
subject: SubjectRefSchema,
|
|
42
|
+
}) as z.ZodType<BiomeAvailabilityGrant>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `BiomeOrigin` — the packaging-time PROVENANCE posture carried on a biome
|
|
5
|
+
* manifest (`xema.trustTier` in `xema-biome.json`). This is the value
|
|
6
|
+
* available at BUILD/resolve time and the one a distribution `trustPolicy`
|
|
7
|
+
* gates on (e.g. a locked appliance allows only `first-party`).
|
|
8
|
+
*
|
|
9
|
+
* Distinct from the richer 6-value publication/install provenance
|
|
10
|
+
* (`BiomeTrustTier`), which is assigned later at store-publish / install time
|
|
11
|
+
* and is not knowable from source. Keep the two separate — the distribution
|
|
12
|
+
* trust gate operates on origin, not on install-time provenance.
|
|
13
|
+
*
|
|
14
|
+
* Closed set; new values are a kernel change. (Seam: the biome-sdk manifest's
|
|
15
|
+
* own 2-value `BiomeTrustTierSchema` should migrate to import this enum so the
|
|
16
|
+
* posture has a single source of truth.)
|
|
17
|
+
*/
|
|
18
|
+
export enum BiomeOrigin {
|
|
19
|
+
FirstParty = 'first-party',
|
|
20
|
+
ThirdParty = 'third-party',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const BiomeOriginSchema = z.nativeEnum(BiomeOrigin);
|
|
24
|
+
|
|
25
|
+
/** The default origin applied when a manifest omits the field. */
|
|
26
|
+
export const DEFAULT_BIOME_ORIGIN = BiomeOrigin.ThirdParty;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `BiomeTarget` — the runtime surface a biome ships for. A `server` biome runs
|
|
5
|
+
* as a backend workload (NestJS service / worker); a `web` biome is a federated
|
|
6
|
+
* frontend module mounted in the host shell. Mirrors the biome-sdk manifest
|
|
7
|
+
* `xema.target` discriminant; lives here as the canonical contract so the
|
|
8
|
+
* distribution lockfile can type the resolved surface without depending on the
|
|
9
|
+
* (Layer 1) biome-sdk.
|
|
10
|
+
*/
|
|
11
|
+
export enum BiomeTarget {
|
|
12
|
+
Server = 'server',
|
|
13
|
+
Web = 'web',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const BiomeTargetSchema = z.nativeEnum(BiomeTarget);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `BiomeTier` — the canonical DEPENDENCY/BOOT tier of a biome.
|
|
5
|
+
*
|
|
6
|
+
* This is the axis that governs which biomes a biome may depend on and the
|
|
7
|
+
* boot order (kernel boots first, then system, then base, then platform). It
|
|
8
|
+
* is DISTINCT from two other biome dimensions that share overlapping string
|
|
9
|
+
* values but mean different things:
|
|
10
|
+
*
|
|
11
|
+
* - `BiomeScope` (`biome-scope.ts`) — the INSTALLATION scope
|
|
12
|
+
* (`system|org|project|sandbox`): where an installation lives.
|
|
13
|
+
* - `BiomeTrustTier` (`biome-trust-tier.ts`) — PROVENANCE/origin
|
|
14
|
+
* (`first-party|verified-store|community-store|…`).
|
|
15
|
+
*
|
|
16
|
+
* Closed set, ordered low→high. `third-party` is intentionally NOT a tier
|
|
17
|
+
* value — origin/trust is carried by `BiomeTrustTier`, not by the dependency
|
|
18
|
+
* tier (the two axes were previously conflated in the biome-sdk
|
|
19
|
+
* `BiomeScopeSchema`). New tiers are a kernel change.
|
|
20
|
+
*
|
|
21
|
+
* String values match the on-wire `xema.scope` field of `xema-biome.json`
|
|
22
|
+
* (the manifest field name remains `scope` for now; the distribution tooling
|
|
23
|
+
* maps `xema.scope` → `BiomeTier`).
|
|
24
|
+
*/
|
|
25
|
+
export enum BiomeTier {
|
|
26
|
+
Kernel = 'kernel',
|
|
27
|
+
System = 'system',
|
|
28
|
+
Base = 'base',
|
|
29
|
+
Platform = 'platform',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const BiomeTierSchema = z.nativeEnum(BiomeTier);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Tier precedence, low→high. A biome of tier `T` may depend only on biomes
|
|
36
|
+
* whose tier index is `<=` its own. Index 0 (`Kernel`) is the always-shipped
|
|
37
|
+
* floor of every distribution.
|
|
38
|
+
*/
|
|
39
|
+
export const BIOME_TIER_ORDER: readonly BiomeTier[] = [
|
|
40
|
+
BiomeTier.Kernel,
|
|
41
|
+
BiomeTier.System,
|
|
42
|
+
BiomeTier.Base,
|
|
43
|
+
BiomeTier.Platform,
|
|
44
|
+
];
|
|
@@ -121,6 +121,20 @@ export enum ContributionKind {
|
|
|
121
121
|
* upsert by `ref`, so they cannot drift.
|
|
122
122
|
*/
|
|
123
123
|
Capability = 'capability',
|
|
124
|
+
|
|
125
|
+
// -- Domain stage machines (MailOps asset lifecycle) ---------------------
|
|
126
|
+
/**
|
|
127
|
+
* A deterministic asset stage machine contributed by a domain biome to a
|
|
128
|
+
* stage-machine host (today: `mailops-api`). The descriptor is pure data —
|
|
129
|
+
* an asset type plus an ordered list of stages, each non-initial stage
|
|
130
|
+
* declaring the evidence kinds that must be present to reach it. The host
|
|
131
|
+
* compiles the descriptor into runtime predicates over the asset's evidence
|
|
132
|
+
* timeline (`computeStage`). The kernel owns only this enum member; the
|
|
133
|
+
* descriptor's manifest schema is owned by the ingesting host (mirroring
|
|
134
|
+
* `ArtifactType`, whose schema lives in `artifact-store-api`) because the
|
|
135
|
+
* stage machine is a host-domain concept, not a kernel one.
|
|
136
|
+
*/
|
|
137
|
+
StageMachine = 'stage-machine',
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
/**
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
BiomeTierSchema,
|
|
4
|
+
BiomeTargetSchema,
|
|
5
|
+
BiomeOriginSchema,
|
|
6
|
+
type BiomeTier,
|
|
7
|
+
type BiomeTarget,
|
|
8
|
+
type BiomeOrigin,
|
|
9
|
+
} from '../../biome';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A single biome as resolved into a distribution lockfile. Version-pinned and
|
|
13
|
+
* (once images are built) content-addressed. `imageDigest` is populated by the
|
|
14
|
+
* image-manifest step (`images.lock.json`) and may be absent in the pure biome
|
|
15
|
+
* lockfile before images are built.
|
|
16
|
+
*/
|
|
17
|
+
export interface LockedBiome {
|
|
18
|
+
id: string;
|
|
19
|
+
version: string;
|
|
20
|
+
tier: BiomeTier;
|
|
21
|
+
target: BiomeTarget;
|
|
22
|
+
/** Provenance posture from the manifest (gated by the distribution trustPolicy). */
|
|
23
|
+
origin: BiomeOrigin;
|
|
24
|
+
/** Whether the org may disable this biome once shipped (cannot-disable). */
|
|
25
|
+
mandatory: boolean;
|
|
26
|
+
/** Source repo + path the biome was resolved from (provenance for the build). */
|
|
27
|
+
repo: string;
|
|
28
|
+
path: string;
|
|
29
|
+
/** Set by the image-manifest resolver; `image@sha256:<digest>`. */
|
|
30
|
+
imageDigest?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const LockedBiomeSchema = z.object({
|
|
34
|
+
id: z.string().min(1),
|
|
35
|
+
version: z.string().min(1),
|
|
36
|
+
tier: BiomeTierSchema,
|
|
37
|
+
target: BiomeTargetSchema,
|
|
38
|
+
origin: BiomeOriginSchema,
|
|
39
|
+
mandatory: z.boolean(),
|
|
40
|
+
repo: z.string().min(1),
|
|
41
|
+
path: z.string().min(1),
|
|
42
|
+
imageDigest: z.string().min(1).optional(),
|
|
43
|
+
}) as z.ZodType<LockedBiome>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* `DistributionLock` — the deterministic, resolved output of a `Distribution`.
|
|
47
|
+
* THE single artifact every consumer reads (deploy generator, test-suite
|
|
48
|
+
* mapping, biome-host boot filter, appliance build). No consumer re-applies the
|
|
49
|
+
* distribution rules — the lockfile is the hard boundary.
|
|
50
|
+
*
|
|
51
|
+
* `resolvedAt` / `inputHash` are stamped by the resolver tooling, not the
|
|
52
|
+
* kernel (kernel contracts hold no clock); both optional so the type is usable
|
|
53
|
+
* mid-resolution.
|
|
54
|
+
*/
|
|
55
|
+
export interface DistributionLock {
|
|
56
|
+
schemaVersion: 1;
|
|
57
|
+
distributionId: string;
|
|
58
|
+
biomes: readonly LockedBiome[];
|
|
59
|
+
/** ISO-8601 timestamp the resolver stamped (tooling-supplied). */
|
|
60
|
+
resolvedAt?: string;
|
|
61
|
+
/** Hash of the resolver inputs (manifest + index) for drift detection. */
|
|
62
|
+
inputHash?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const DistributionLockSchema = z.object({
|
|
66
|
+
schemaVersion: z.literal(1),
|
|
67
|
+
distributionId: z.string().min(1),
|
|
68
|
+
biomes: z.array(LockedBiomeSchema).readonly(),
|
|
69
|
+
resolvedAt: z.string().min(1).optional(),
|
|
70
|
+
inputHash: z.string().min(1).optional(),
|
|
71
|
+
}) as z.ZodType<DistributionLock>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Parse + validate a raw `distribution.lock.json`. Fail-fast on any shape error
|
|
75
|
+
* — the lockfile is the hard boundary every consumer reads, so a malformed lock
|
|
76
|
+
* must never be silently tolerated.
|
|
77
|
+
*/
|
|
78
|
+
export function parseDistributionLock(raw: unknown): DistributionLock {
|
|
79
|
+
const result = DistributionLockSchema.safeParse(raw);
|
|
80
|
+
if (!result.success) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Invalid distribution.lock.json: ${result.error.issues
|
|
83
|
+
.map((i) => `[${i.path.join('.')}] ${i.message}`)
|
|
84
|
+
.join('; ')}`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return result.data;
|
|
88
|
+
}
|