@xemahq/kernel-contracts 0.33.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/app-runtime/index.d.ts +3 -0
  2. package/dist/app-runtime/index.d.ts.map +1 -1
  3. package/dist/app-runtime/index.js +3 -0
  4. package/dist/app-runtime/index.js.map +1 -1
  5. package/dist/app-runtime/lib/app-channel.d.ts +7 -0
  6. package/dist/app-runtime/lib/app-channel.d.ts.map +1 -0
  7. package/dist/app-runtime/lib/app-channel.js +11 -0
  8. package/dist/app-runtime/lib/app-channel.js.map +1 -0
  9. package/dist/app-runtime/lib/app-release.d.ts +24 -0
  10. package/dist/app-runtime/lib/app-release.d.ts.map +1 -0
  11. package/dist/app-runtime/lib/app-release.js +29 -0
  12. package/dist/app-runtime/lib/app-release.js.map +1 -0
  13. package/dist/app-runtime/lib/app.d.ts +3 -0
  14. package/dist/app-runtime/lib/app.d.ts.map +1 -1
  15. package/dist/app-runtime/lib/app.js +19 -4
  16. package/dist/app-runtime/lib/app.js.map +1 -1
  17. package/dist/app-runtime/lib/branding-config.d.ts.map +1 -1
  18. package/dist/app-runtime/lib/branding-config.js.map +1 -1
  19. package/dist/app-runtime/lib/delegated-session.js +1 -1
  20. package/dist/app-runtime/lib/delegated-session.js.map +1 -1
  21. package/dist/app-runtime/lib/surface-kind.d.ts +8 -0
  22. package/dist/app-runtime/lib/surface-kind.d.ts.map +1 -0
  23. package/dist/app-runtime/lib/surface-kind.js +12 -0
  24. package/dist/app-runtime/lib/surface-kind.js.map +1 -0
  25. package/dist/capability/index.d.ts +1 -0
  26. package/dist/capability/index.d.ts.map +1 -1
  27. package/dist/capability/index.js +1 -0
  28. package/dist/capability/index.js.map +1 -1
  29. package/dist/capability/lib/first-party-capability-domains.d.ts +29 -0
  30. package/dist/capability/lib/first-party-capability-domains.d.ts.map +1 -0
  31. package/dist/capability/lib/first-party-capability-domains.js +35 -0
  32. package/dist/capability/lib/first-party-capability-domains.js.map +1 -0
  33. package/dist/principal/index.d.ts +6 -0
  34. package/dist/principal/index.d.ts.map +1 -0
  35. package/dist/principal/index.js +22 -0
  36. package/dist/principal/index.js.map +1 -0
  37. package/dist/principal/lib/app-invocation-identity.d.ts +22 -0
  38. package/dist/principal/lib/app-invocation-identity.d.ts.map +1 -0
  39. package/dist/principal/lib/app-invocation-identity.js +36 -0
  40. package/dist/principal/lib/app-invocation-identity.js.map +1 -0
  41. package/dist/principal/lib/clamp-authority.d.ts +4 -0
  42. package/dist/principal/lib/clamp-authority.d.ts.map +1 -0
  43. package/dist/principal/lib/clamp-authority.js +23 -0
  44. package/dist/principal/lib/clamp-authority.js.map +1 -0
  45. package/dist/principal/lib/delegation-chain.d.ts +26 -0
  46. package/dist/principal/lib/delegation-chain.d.ts.map +1 -0
  47. package/dist/principal/lib/delegation-chain.js +81 -0
  48. package/dist/principal/lib/delegation-chain.js.map +1 -0
  49. package/dist/principal/lib/delegation-grant.d.ts +10 -0
  50. package/dist/principal/lib/delegation-grant.d.ts.map +1 -0
  51. package/dist/principal/lib/delegation-grant.js +12 -0
  52. package/dist/principal/lib/delegation-grant.js.map +1 -0
  53. package/dist/principal/lib/execution-principal.d.ts +20 -0
  54. package/dist/principal/lib/execution-principal.d.ts.map +1 -0
  55. package/dist/principal/lib/execution-principal.js +22 -0
  56. package/dist/principal/lib/execution-principal.js.map +1 -0
  57. package/package.json +1 -1
  58. package/src/app-runtime/index.ts +3 -0
  59. package/src/app-runtime/lib/app-channel.ts +32 -0
  60. package/src/app-runtime/lib/app-release.ts +90 -0
  61. package/src/app-runtime/lib/app.ts +48 -17
  62. package/src/app-runtime/lib/branding-config.ts +12 -6
  63. package/src/app-runtime/lib/delegated-session.ts +2 -2
  64. package/src/app-runtime/lib/surface-kind.ts +30 -0
  65. package/src/capability/index.ts +1 -0
  66. package/src/capability/lib/first-party-capability-domains.ts +76 -0
  67. package/src/principal/index.ts +5 -0
  68. package/src/principal/lib/app-invocation-identity.ts +95 -0
  69. package/src/principal/lib/clamp-authority.ts +64 -0
  70. package/src/principal/lib/delegation-chain.ts +145 -0
  71. package/src/principal/lib/delegation-grant.ts +36 -0
  72. package/src/principal/lib/execution-principal.ts +74 -0
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DelegationChainError = exports.DelegationErrorCodeSchema = exports.DelegationErrorCode = exports.MAX_DELEGATION_DEPTH = void 0;
4
+ exports.resolveDelegationChain = resolveDelegationChain;
5
+ const zod_1 = require("zod");
6
+ const subject_1 = require("../../subject");
7
+ exports.MAX_DELEGATION_DEPTH = 3;
8
+ var DelegationErrorCode;
9
+ (function (DelegationErrorCode) {
10
+ DelegationErrorCode["ChainTooDeep"] = "DELEGATION_CHAIN_TOO_DEEP";
11
+ DelegationErrorCode["Cycle"] = "DELEGATION_CHAIN_CYCLE";
12
+ DelegationErrorCode["Discontinuous"] = "DELEGATION_CHAIN_DISCONTINUOUS";
13
+ DelegationErrorCode["NotAnchoredAtActor"] = "DELEGATION_CHAIN_NOT_ANCHORED_AT_ACTOR";
14
+ DelegationErrorCode["NotAnchoredAtExecutor"] = "DELEGATION_CHAIN_NOT_ANCHORED_AT_EXECUTOR";
15
+ DelegationErrorCode["EmptyChainMismatch"] = "DELEGATION_CHAIN_EMPTY_MISMATCH";
16
+ })(DelegationErrorCode || (exports.DelegationErrorCode = DelegationErrorCode = {}));
17
+ exports.DelegationErrorCodeSchema = zod_1.z.nativeEnum(DelegationErrorCode);
18
+ class DelegationChainError extends Error {
19
+ code;
20
+ constructor(args) {
21
+ super(args.message);
22
+ this.name = 'DelegationChainError';
23
+ this.code = args.code;
24
+ }
25
+ }
26
+ exports.DelegationChainError = DelegationChainError;
27
+ function subjectsEqual(a, b) {
28
+ return (0, subject_1.subjectRefToString)(a) === (0, subject_1.subjectRefToString)(b);
29
+ }
30
+ function resolveDelegationChain(args) {
31
+ const { actor, executor, chain } = args;
32
+ if (chain.length === 0) {
33
+ if (!subjectsEqual(actor, executor)) {
34
+ throw new DelegationChainError({
35
+ code: DelegationErrorCode.EmptyChainMismatch,
36
+ message: `Empty delegation chain requires actor === executor, but actor "${(0, subject_1.subjectRefToString)(actor)}" ≠ executor "${(0, subject_1.subjectRefToString)(executor)}".`,
37
+ });
38
+ }
39
+ return Object.freeze([]);
40
+ }
41
+ if (chain.length > exports.MAX_DELEGATION_DEPTH) {
42
+ throw new DelegationChainError({
43
+ code: DelegationErrorCode.ChainTooDeep,
44
+ message: `Delegation chain has ${chain.length} hops; the maximum is ${exports.MAX_DELEGATION_DEPTH}.`,
45
+ });
46
+ }
47
+ if (!subjectsEqual(chain[0].from, actor)) {
48
+ throw new DelegationChainError({
49
+ code: DelegationErrorCode.NotAnchoredAtActor,
50
+ message: `Delegation chain must start at actor "${(0, subject_1.subjectRefToString)(actor)}", but its first hop starts at "${(0, subject_1.subjectRefToString)(chain[0].from)}".`,
51
+ });
52
+ }
53
+ const last = chain[chain.length - 1];
54
+ if (!subjectsEqual(last.to, executor)) {
55
+ throw new DelegationChainError({
56
+ code: DelegationErrorCode.NotAnchoredAtExecutor,
57
+ message: `Delegation chain must end at executor "${(0, subject_1.subjectRefToString)(executor)}", but its last hop ends at "${(0, subject_1.subjectRefToString)(last.to)}".`,
58
+ });
59
+ }
60
+ const seen = new Set();
61
+ const firstKey = (0, subject_1.subjectRefToString)(chain[0].from);
62
+ seen.add(firstKey);
63
+ for (let i = 0; i < chain.length; i += 1) {
64
+ if (i > 0 && !subjectsEqual(chain[i - 1].to, chain[i].from)) {
65
+ throw new DelegationChainError({
66
+ code: DelegationErrorCode.Discontinuous,
67
+ message: `Delegation chain is not contiguous at hop ${i}: previous "to" "${(0, subject_1.subjectRefToString)(chain[i - 1].to)}" ≠ this "from" "${(0, subject_1.subjectRefToString)(chain[i].from)}".`,
68
+ });
69
+ }
70
+ const toKey = (0, subject_1.subjectRefToString)(chain[i].to);
71
+ if (seen.has(toKey)) {
72
+ throw new DelegationChainError({
73
+ code: DelegationErrorCode.Cycle,
74
+ message: `Delegation chain contains a cycle: subject "${toKey}" appears more than once.`,
75
+ });
76
+ }
77
+ seen.add(toKey);
78
+ }
79
+ return Object.freeze([...chain]);
80
+ }
81
+ //# sourceMappingURL=delegation-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-chain.js","sourceRoot":"","sources":["../../../src/principal/lib/delegation-chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ import { type SubjectRef } from '../../subject';
3
+ export interface DelegationGrant {
4
+ from: SubjectRef;
5
+ to: SubjectRef;
6
+ grantedAt: string;
7
+ reason?: string;
8
+ }
9
+ export declare const DelegationGrantSchema: z.ZodType<DelegationGrant>;
10
+ //# sourceMappingURL=delegation-grant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-grant.d.ts","sourceRoot":"","sources":["../../../src/principal/lib/delegation-grant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAkBlE,MAAM,WAAW,eAAe;IAE9B,IAAI,EAAE,UAAU,CAAC;IAEjB,EAAE,EAAE,UAAU,CAAC;IAEf,SAAS,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,qBAAqB,EAK5B,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DelegationGrantSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const subject_1 = require("../../subject");
6
+ exports.DelegationGrantSchema = zod_1.z.object({
7
+ from: subject_1.SubjectRefSchema,
8
+ to: subject_1.SubjectRefSchema,
9
+ grantedAt: zod_1.z.string().datetime(),
10
+ reason: zod_1.z.string().min(1).optional(),
11
+ });
12
+ //# sourceMappingURL=delegation-grant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-grant.js","sourceRoot":"","sources":["../../../src/principal/lib/delegation-grant.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,2CAAkE;AA6BrD,QAAA,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,0BAAgB;IACtB,EAAE,EAAE,0BAAgB;IACpB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAA+B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { type SubjectRef, type TokenClass } from '../../subject';
3
+ import { type ExecutionEnvironmentRef } from '../../execution-environment';
4
+ import { type AppChannel } from '../../app-runtime';
5
+ import { type DelegationGrant } from './delegation-grant';
6
+ export interface ExecutionPrincipal {
7
+ actor: SubjectRef;
8
+ executor: SubjectRef;
9
+ delegationChain: DelegationGrant[];
10
+ tokenClass: TokenClass;
11
+ environment: ExecutionEnvironmentRef;
12
+ orgId: string;
13
+ appId?: string;
14
+ releaseId?: string;
15
+ channel?: AppChannel;
16
+ tenantId?: string;
17
+ purpose?: string;
18
+ }
19
+ export declare const ExecutionPrincipalSchema: z.ZodType<ExecutionPrincipal>;
20
+ //# sourceMappingURL=execution-principal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-principal.d.ts","sourceRoot":"","sources":["../../../src/principal/lib/execution-principal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAwBjF,MAAM,WAAW,kBAAkB;IAEjC,KAAK,EAAE,UAAU,CAAC;IAElB,QAAQ,EAAE,UAAU,CAAC;IAErB,eAAe,EAAE,eAAe,EAAE,CAAC;IAEnC,UAAU,EAAE,UAAU,CAAC;IAEvB,WAAW,EAAE,uBAAuB,CAAC;IAErC,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,OAAO,CAAC,EAAE,UAAU,CAAC;IAErB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,wBAAwB,EAY/B,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExecutionPrincipalSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const subject_1 = require("../../subject");
6
+ const execution_environment_1 = require("../../execution-environment");
7
+ const app_runtime_1 = require("../../app-runtime");
8
+ const delegation_grant_1 = require("./delegation-grant");
9
+ exports.ExecutionPrincipalSchema = zod_1.z.object({
10
+ actor: subject_1.SubjectRefSchema,
11
+ executor: subject_1.SubjectRefSchema,
12
+ delegationChain: zod_1.z.array(delegation_grant_1.DelegationGrantSchema),
13
+ tokenClass: subject_1.TokenClassSchema,
14
+ environment: execution_environment_1.ExecutionEnvironmentRefSchema,
15
+ orgId: zod_1.z.string().min(1),
16
+ appId: zod_1.z.string().min(1).optional(),
17
+ releaseId: zod_1.z.string().min(1).optional(),
18
+ channel: app_runtime_1.AppChannelSchema.optional(),
19
+ tenantId: zod_1.z.string().min(1).optional(),
20
+ purpose: zod_1.z.string().min(1).optional(),
21
+ });
22
+ //# sourceMappingURL=execution-principal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-principal.js","sourceRoot":"","sources":["../../../src/principal/lib/execution-principal.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,2CAKuB;AACvB,uEAGqC;AACrC,mDAAsE;AACtE,yDAAiF;AAiDpE,QAAA,wBAAwB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC/C,KAAK,EAAE,0BAAgB;IACvB,QAAQ,EAAE,0BAAgB;IAC1B,eAAe,EAAE,OAAC,CAAC,KAAK,CAAC,wCAAqB,CAAC;IAC/C,UAAU,EAAE,0BAAgB;IAC5B,WAAW,EAAE,qDAA6B;IAC1C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,OAAO,EAAE,8BAAgB,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACtC,CAAkC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/kernel-contracts",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "description": "Consolidated Xema OS kernel wire contracts — pure types + zod schemas for the kernel protocol surfaces. One package, one npm scope, wildcard per-surface subpath exports. No framework/runtime deps.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
@@ -5,4 +5,7 @@ export * from './lib/delegated-session';
5
5
  export * from './lib/app-client';
6
6
  export * from './lib/app-lockfile';
7
7
  export * from './lib/branding-config';
8
+ export * from './lib/surface-kind';
9
+ export * from './lib/app-channel';
10
+ export * from './lib/app-release';
8
11
  export * from './lib/app';
@@ -0,0 +1,32 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * `AppChannel` — the closed set of channels an App is exercised through.
5
+ *
6
+ * A channel is *which data and which definition* an invocation sees:
7
+ *
8
+ * - `Preview` — the in-progress definition and its isolated data. The
9
+ * user-facing word is **"Editing"**.
10
+ * - `Live` — the active release's definition and the real data. The
11
+ * user-facing word is **"Live"**.
12
+ *
13
+ * A channel is NOT the same axis as an `ExecutionEnvironment`. An
14
+ * `ExecutionEnvironment` is *what may be touched* (which capabilities /
15
+ * resources are in scope); an `AppChannel` is *which definition + which data*.
16
+ * They are orthogonal and combine: preview RUNS IN `environment:sandbox`, live
17
+ * RUNS IN `environment:app`. Do not collapse the two.
18
+ *
19
+ * This enum lands in Wave 0.1 (not Wave 5) because it is keyed on well before
20
+ * Wave 5: Wave 1.1's `ownerRef`, Wave 3.2's `AppRoleBinding.channel`, and Wave
21
+ * 4.1's `AppRun.channel` all reference it. Only the enum lands now — its
22
+ * runtime semantics (data separation, denied side effects, no scheduled
23
+ * automations on preview) are Wave 5.1.
24
+ *
25
+ * Values are stable wire strings — never compare against a free-form string.
26
+ */
27
+ export enum AppChannel {
28
+ Preview = 'preview',
29
+ Live = 'live',
30
+ }
31
+
32
+ export const AppChannelSchema = z.nativeEnum(AppChannel);
@@ -0,0 +1,90 @@
1
+ import { z } from 'zod';
2
+ import { AppLockfileSchema, type AppLockfile } from './app-lockfile';
3
+
4
+ /**
5
+ * `AppReleaseState` — the closed lifecycle of a single `AppRelease` row.
6
+ *
7
+ * ```
8
+ * preparing → prepared → activating → active → superseded
9
+ * └──────────┴───────────┴──────────────→ failed
10
+ * ```
11
+ *
12
+ * - `preparing` — a candidate release is being assembled (steps 1–5 of D2).
13
+ * - `prepared` — assembled and validated, migration NOT yet executed.
14
+ * - `activating` — the migration is executing and the pointer flip is in
15
+ * flight (steps 6–7).
16
+ * - `active` — the pointer (`App.activeReleaseId`) currently targets this
17
+ * release; it is the ONE release visible to every runtime surface.
18
+ * - `superseded` — was `active`, replaced by a later activation; retained for
19
+ * rollback within the retention window (D3).
20
+ * - `failed` — prepare or activation aborted; invisible, garbage-collected.
21
+ */
22
+ export enum AppReleaseState {
23
+ Preparing = 'preparing',
24
+ Prepared = 'prepared',
25
+ Activating = 'activating',
26
+ Active = 'active',
27
+ Superseded = 'superseded',
28
+ Failed = 'failed',
29
+ }
30
+
31
+ export const AppReleaseStateSchema = z.nativeEnum(AppReleaseState);
32
+
33
+ /**
34
+ * `AppRelease` — an immutable candidate/active snapshot of an App's published
35
+ * definition, its resolved lockfile, and the schema-change plan applied for it.
36
+ *
37
+ * **Publishing is a distributed release, not a transaction (D2).** The
38
+ * definition lives in app-forge's database, the DDL runs in an org database,
39
+ * the `App` lives in app-runtime, agents/skills/workflows live in their own
40
+ * registries, and grants live in authorization-api. **No transaction spans
41
+ * these five systems.** Publish therefore runs an eight-step
42
+ * prepare-and-activate protocol:
43
+ *
44
+ * ```
45
+ * 1. create an immutable candidate AppRelease (invisible)
46
+ * 2. prepare the schema change plan (validated, not applied)
47
+ * 3. prepare agent / skill / workflow versions (drafts in their registries)
48
+ * 4. validate capability bindings and grants (fail here, cheaply)
49
+ * 5. write the immutable AppRelease manifest + lockfile
50
+ * 6. execute the migration (idempotent, one txn per plan)
51
+ * 7. atomically flip App.activeReleaseId (the ONLY atomic operation)
52
+ * 8. publish activation through the transactional outbox
53
+ * ```
54
+ *
55
+ * Because no transaction spans the five systems, **the only atomic operation is
56
+ * flipping `App.activeReleaseId`** (step 7) — moving one pointer. Everything
57
+ * else is prepared idempotently and made visible only by that flip.
58
+ *
59
+ * **Preparing/prepared/failed releases are invisible + garbage-collected (D3).**
60
+ * A release that is not `active` (or a retained `superseded`) is visible to NO
61
+ * runtime surface and is garbage-collected after a TTL. Rollback is simply
62
+ * repointing `activeReleaseId` to a prior release — which is sound ONLY because
63
+ * the publish path tombstones (marks deprecated) rather than physically drops:
64
+ * an older release can still run against a tombstoned-but-present column.
65
+ */
66
+ export interface AppRelease {
67
+ id: string;
68
+ appId: string;
69
+ version: number;
70
+ definition: unknown;
71
+ lockfile: AppLockfile;
72
+ schemaPlan: unknown;
73
+ state: AppReleaseState;
74
+ preparedAt?: string;
75
+ activatedAt?: string;
76
+ }
77
+
78
+ export const AppReleaseSchema = z.object({
79
+ id: z.string().min(1),
80
+ appId: z.string().min(1),
81
+ version: z.number().int().positive({
82
+ message: 'AppRelease.version must be a positive integer (1-based).',
83
+ }),
84
+ definition: z.unknown(),
85
+ lockfile: AppLockfileSchema,
86
+ schemaPlan: z.unknown(),
87
+ state: AppReleaseStateSchema,
88
+ preparedAt: z.string().min(1).optional(),
89
+ activatedAt: z.string().min(1).optional(),
90
+ }) as z.ZodType<AppRelease>;
@@ -15,6 +15,7 @@ import { BiomeInstallSchema, type BiomeInstall } from './biome-install';
15
15
  import { AudiencePolicySchema, type AudiencePolicy } from './audience-policy';
16
16
  import { BrandingConfigSchema, type BrandingConfig } from './branding-config';
17
17
  import { AppLockfileSchema, type AppLockfile } from './app-lockfile';
18
+ import { SurfaceKind, SurfaceKindSchema } from './surface-kind';
18
19
 
19
20
  /**
20
21
  * Per-App tightening on top of the base `CapabilityPolicy` carried by an
@@ -47,12 +48,22 @@ export const CapabilityPolicyOverrideSchema = z.object({
47
48
  *
48
49
  * Invariants enforced at parse time:
49
50
  *
50
- * - `installedBiomes` MUST be non-empty an App with zero biomes has no
51
- * capability surface, so this is a fail-fast policy bug.
51
+ * - `installedBiomes` MUST be non-empty for a `Composed` or `Coded` App one
52
+ * with zero biomes would have no capability surface, so that is a fail-fast
53
+ * policy bug. A **`Declared` App is exempt**: an app-forge definition installs
54
+ * no biomes at all. Its capability surface comes from `capabilityPolicy` and
55
+ * the declarative runtime that hosts it, not from a biome install. Requiring a
56
+ * biome here would force every declared app to fabricate one, which is how a
57
+ * fail-fast invariant quietly becomes a lie.
52
58
  * - `audiences` MUST be non-empty — an App with zero audiences is
53
59
  * unreachable; declare at least one (e.g. `InternalOrg`) explicitly.
54
60
  * - `defaultZone` and `lockfile` are REQUIRED (no implicit default environment,
55
61
  * no "best-effort" un-pinned execution).
62
+ * - `surface` is REQUIRED — the tier the App is authored at (`Declared` /
63
+ * `Composed` / `Coded`).
64
+ * - `activeReleaseId` is nullable: an App with no active release has NEVER
65
+ * published. It is the ONLY atomic publish switch (D2) — moving this pointer
66
+ * is what makes a prepared `AppRelease` visible to every runtime surface.
56
67
  *
57
68
  * Per-App tightening on top of a environment's `CapabilityPolicy` is carried by
58
69
  * `capabilityPolicy` (intersect-only at the gateway, never widen).
@@ -65,20 +76,40 @@ export interface App {
65
76
  capabilityPolicy: CapabilityPolicyOverride[];
66
77
  branding: BrandingConfig;
67
78
  lockfile: AppLockfile;
79
+ surface: SurfaceKind;
80
+ activeReleaseId?: string;
68
81
  }
69
82
 
70
- export const AppSchema = z.object({
71
- ref: XemaObjectRefSchema,
72
- installedBiomes: z.array(BiomeInstallSchema).min(1, {
73
- message:
74
- 'App.installedBiomes must contain at least one BiomeInstall; an App with zero biomes has no capability surface.',
75
- }),
76
- defaultZone: ExecutionEnvironmentRefSchema,
77
- audiences: z.array(AudiencePolicySchema).min(1, {
78
- message:
79
- 'App.audiences must contain at least one AudiencePolicy; an App with zero audiences is unreachable.',
80
- }),
81
- capabilityPolicy: z.array(CapabilityPolicyOverrideSchema),
82
- branding: BrandingConfigSchema,
83
- lockfile: AppLockfileSchema,
84
- }) as z.ZodType<App>;
83
+ export const AppSchema = z
84
+ .object({
85
+ ref: XemaObjectRefSchema,
86
+ installedBiomes: z.array(BiomeInstallSchema),
87
+ defaultZone: ExecutionEnvironmentRefSchema,
88
+ audiences: z.array(AudiencePolicySchema).min(1, {
89
+ message:
90
+ 'App.audiences must contain at least one AudiencePolicy; an App with zero audiences is unreachable.',
91
+ }),
92
+ capabilityPolicy: z.array(CapabilityPolicyOverrideSchema),
93
+ branding: BrandingConfigSchema,
94
+ lockfile: AppLockfileSchema,
95
+ surface: SurfaceKindSchema,
96
+ activeReleaseId: z.string().min(1).optional(),
97
+ })
98
+ .superRefine((app, ctx) => {
99
+ // A Declared App (an app-forge definition) installs no biomes: its capability
100
+ // surface is `capabilityPolicy` plus the declarative runtime that hosts it.
101
+ // Composed and Coded Apps run biome-provided code, so zero biomes there IS a
102
+ // policy bug and must fail fast.
103
+ if (app.surface !== SurfaceKind.Declared && app.installedBiomes.length === 0) {
104
+ ctx.addIssue({
105
+ code: 'too_small',
106
+ minimum: 1,
107
+ origin: 'array',
108
+ inclusive: true,
109
+ path: ['installedBiomes'],
110
+ message:
111
+ `App.installedBiomes must contain at least one BiomeInstall for a '${app.surface}' App; ` +
112
+ 'one with zero biomes has no capability surface. Only a `declared` App may install none.',
113
+ });
114
+ }
115
+ }) as unknown as z.ZodType<App>;
@@ -15,16 +15,22 @@ const PRIMARY_COLOR_REGEX =
15
15
  /^(?:#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(?:,\s*(?:0|1|0?\.\d+)\s*)?\))$/;
16
16
 
17
17
  /**
18
- * `BrandingConfig` — per-App visual branding. Used by the
19
- * public ingress (`app-runtime-api`) and any embed snippet to theme the
20
- * audience-facing UI. The shape is intentionally minimal:
18
+ * `BrandingConfig` — per-App visual branding. The shape is intentionally
19
+ * minimal:
21
20
  *
22
21
  * - `displayName` is REQUIRED — every audience-facing surface needs a
23
22
  * human-readable label; no silent fallback to the App slug.
24
23
  * - `primaryColor` is validated against a strict hex / rgb(a) grammar.
25
- * - `cssTokens` is the escape hatch for richer theming — keys map to CSS
26
- * custom-property names (without the leading `--`); the host CSS
27
- * pipeline interprets the values.
24
+ * - `cssTokens` is the escape hatch for richer theming — keys are intended to
25
+ * map to CSS custom-property names (without the leading `--`).
26
+ *
27
+ * STATUS (2026-07-10): this is a VALIDATED CONTRACT ONLY. Nothing applies it at
28
+ * runtime yet — `logoUrl` and `primaryColor` never reach the DOM, and there is
29
+ * no host CSS pipeline reading `cssTokens`. An earlier version of this docstring
30
+ * claimed the public ingress themes the audience-facing UI with it; that reader
31
+ * does not exist. The runtime branding applier (a theming provider writing CSS
32
+ * custom properties, resolved per-sub-tenant from `AppRoleBinding.tenantId`) is
33
+ * Wave 8.4 — do not assume a value set here has any visual effect until then.
28
34
  */
29
35
  export interface BrandingConfig {
30
36
  displayName: string;
@@ -13,7 +13,7 @@ import {
13
13
  * for an `ExternalSubject` audience:
14
14
  *
15
15
  * ```
16
- * sub = external-user:<externalId> (or anon:<random>)
16
+ * sub = external-subject:<externalId> (or anon:<random>)
17
17
  * act = app:<appClientId>
18
18
  * org = <orgId>
19
19
  * project = <projectId>
@@ -45,7 +45,7 @@ export interface DelegatedSessionClaims {
45
45
  export const DelegatedSessionClaimsSchema = z.object({
46
46
  sub: z.string().min(1, {
47
47
  message:
48
- 'DelegatedSessionClaims.sub must be a non-empty subject identifier (e.g. `external-user:<id>` or `anon:<random>`).',
48
+ 'DelegatedSessionClaims.sub must be a non-empty subject identifier (e.g. `external-subject:<id>` or `anon:<random>`).',
49
49
  }),
50
50
  act: z.string().min(1, {
51
51
  message:
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * `SurfaceKind` — the closed set of tiers an App surface may be authored at.
5
+ * "Surface" here is HOW an App is defined and rendered, escalating in the
6
+ * amount of hand-written code it carries:
7
+ *
8
+ * - `Declared` — the app-forge definition only, NO code. The app is a
9
+ * declarative document (audiences, biomes, capability policy, pages) that
10
+ * the runtime interprets directly.
11
+ * - `Composed` — the declarative definition PLUS App Functions: declarative
12
+ * surface extended with small authored functions, still hosted by the
13
+ * platform.
14
+ * - `Coded` — an ejected, fully hand-written service + web app that the
15
+ * team owns end-to-end; the platform hosts it but no longer authors it. Which
16
+ * server and web frameworks an ejected app uses is a scaffold decision, not a
17
+ * kernel one — this contract must never name them.
18
+ *
19
+ * NOTE: `OutputSurfaceKind` in `workflow/lib/workspace-manifest-enums.ts` is an
20
+ * UNRELATED workspace-manifest concept. Do not extend it and do not import it.
21
+ *
22
+ * Values are stable wire strings — never compare against a free-form string.
23
+ */
24
+ export enum SurfaceKind {
25
+ Declared = 'declared',
26
+ Composed = 'composed',
27
+ Coded = 'coded',
28
+ }
29
+
30
+ export const SurfaceKindSchema = z.nativeEnum(SurfaceKind);
@@ -1,5 +1,6 @@
1
1
  export * from './lib/capability-ref';
2
2
  export * from './lib/connector-capability-ref';
3
+ export * from './lib/first-party-capability-domains';
3
4
  export * from './lib/capability-grant';
4
5
  export * from './lib/capability-policy';
5
6
  export * from './lib/permission-profile';
@@ -0,0 +1,76 @@
1
+ import { z } from 'zod';
2
+
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ // ── The CLOSED set of first-party capability DOMAINS ──
5
+ //
6
+ // A capability ref is `<domain>:<resource>.<verb>@<major>`. A DOMAIN is
7
+ // "first-party" when a fixed in-the-box Xema platform service owns every ref
8
+ // under it — i.e. the capability-router's static dispatch table resolves it
9
+ // directly (never through an org-provisioned or contributed backing).
10
+ //
11
+ // This is the SINGLE SOURCE OF TRUTH for that membership. It exists so two
12
+ // services can agree without one reaching into the other's code:
13
+ //
14
+ // - `xema-capability-router` builds its static dispatch table from EXACTLY
15
+ // these keys and asserts the two agree at boot (fail-fast on drift).
16
+ // - `capability-registry-api` REFUSES an org `CapabilityProviderBinding`
17
+ // whose ref domain is in this set — an org admin must not be able to bind
18
+ // `kb:page.read@1` / `agent:invoke@1` / `artifact:blob.read@1` to a URL
19
+ // they control and silently shadow the platform data plane.
20
+ //
21
+ // Membership is the router's dispatch keys, in dispatch-registration order.
22
+ // Adding/removing a first-party domain is a coordinated change here PLUS the
23
+ // router's dispatch table — the boot assertion turns any divergence into a
24
+ // crash rather than a silent shadow window.
25
+ // ═══════════════════════════════════════════════════════════════════════════
26
+
27
+ export const FIRST_PARTY_CAPABILITY_DOMAINS = [
28
+ 'xema-shell',
29
+ 'store',
30
+ 'biome',
31
+ 'connector',
32
+ 'kb',
33
+ 'agent',
34
+ 'memory',
35
+ 'model',
36
+ 'model-resolution',
37
+ 'mcp-tool',
38
+ 'workflow',
39
+ 'studio',
40
+ 'interactive-session',
41
+ 'agent-session',
42
+ 'document',
43
+ 'notification',
44
+ 'space',
45
+ 'mailops',
46
+ 'workspace',
47
+ 'worker-runtime',
48
+ 'artifact',
49
+ 'search',
50
+ ] as const;
51
+
52
+ export type FirstPartyCapabilityDomain =
53
+ (typeof FIRST_PARTY_CAPABILITY_DOMAINS)[number];
54
+
55
+ export const FirstPartyCapabilityDomainSchema = z.enum(
56
+ FIRST_PARTY_CAPABILITY_DOMAINS as unknown as [
57
+ FirstPartyCapabilityDomain,
58
+ ...FirstPartyCapabilityDomain[],
59
+ ],
60
+ );
61
+
62
+ const FIRST_PARTY_CAPABILITY_DOMAIN_SET: ReadonlySet<string> = new Set(
63
+ FIRST_PARTY_CAPABILITY_DOMAINS,
64
+ );
65
+
66
+ /**
67
+ * `true` iff `domain` is a first-party platform capability domain. O(1)
68
+ * membership over the closed set above. The write-path shadow refusal and the
69
+ * router's binding-skip defense-in-depth both branch on this — never on an
70
+ * ad-hoc string compare or a hand-maintained second list.
71
+ */
72
+ export function isFirstPartyCapabilityDomain(
73
+ domain: string,
74
+ ): domain is FirstPartyCapabilityDomain {
75
+ return FIRST_PARTY_CAPABILITY_DOMAIN_SET.has(domain);
76
+ }
@@ -0,0 +1,5 @@
1
+ export * from './lib/delegation-grant';
2
+ export * from './lib/delegation-chain';
3
+ export * from './lib/clamp-authority';
4
+ export * from './lib/execution-principal';
5
+ export * from './lib/app-invocation-identity';