@astrale-os/sdk 0.6.0-beta.23 → 0.6.0-beta.25

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 (206) hide show
  1. package/README.md +32 -38
  2. package/dist/application/action/context.d.ts +29 -25
  3. package/dist/application/action/index.d.ts +1 -1
  4. package/dist/application/define.d.ts +3 -1
  5. package/dist/application/define.js +16 -2
  6. package/dist/application/dependency/invoker.d.ts +5 -5
  7. package/dist/application/domain.d.ts +3 -1
  8. package/dist/application/index.d.ts +1 -1
  9. package/dist/application/integration/operation.d.ts +2 -2
  10. package/dist/application/mutation/index.d.ts +1 -1
  11. package/dist/application/query/composite/plan.d.ts +0 -4
  12. package/dist/application/query/composite/plan.js +0 -2
  13. package/dist/application/runtime/workflows.d.ts +1 -1
  14. package/dist/application/runtime/workflows.js +1 -4
  15. package/dist/application/view/define.js +4 -6
  16. package/dist/application/view/frontend.d.ts +2 -2
  17. package/dist/application/view/index.d.ts +1 -1
  18. package/dist/application/view/route.d.ts +0 -14
  19. package/dist/application/view/route.js +1 -64
  20. package/dist/application/workflow/context.d.ts +1 -1
  21. package/dist/application/workflow/define.d.ts +1 -1
  22. package/dist/application/workflow/define.js +1 -1
  23. package/dist/application/workflow/workflow.d.ts +1 -3
  24. package/dist/deployment/adapter/adapter.d.ts +3 -20
  25. package/dist/deployment/adapter/bundle/file.d.ts +1 -1
  26. package/dist/deployment/adapter/define.d.ts +4 -25
  27. package/dist/deployment/adapter/define.js +12 -44
  28. package/dist/deployment/adapter/index.d.ts +0 -2
  29. package/dist/deployment/adapter/release/list.d.ts +1 -2
  30. package/dist/deployment/address/summary.d.ts +3 -7
  31. package/dist/deployment/authoring.d.ts +0 -2
  32. package/dist/deployment/authoring.js +0 -1
  33. package/dist/deployment/build/build.d.ts +6 -0
  34. package/dist/deployment/build/compile.js +2 -0
  35. package/dist/deployment/build/frontend/compilation.d.ts +2 -4
  36. package/dist/deployment/build/frontend/compilation.js +0 -5
  37. package/dist/deployment/build/frontend/digest.js +1 -5
  38. package/dist/deployment/build/material.d.ts +2 -2
  39. package/dist/deployment/build/material.js +28 -13
  40. package/dist/deployment/deployment.d.ts +4 -8
  41. package/dist/deployment/index.d.ts +3 -5
  42. package/dist/deployment/index.js +1 -2
  43. package/dist/deployment/release/addressing.d.ts +2 -9
  44. package/dist/deployment/release/addressing.js +2 -3
  45. package/dist/deployment/release/index.d.ts +0 -2
  46. package/dist/deployment/release/index.js +0 -2
  47. package/dist/deployment/release/release.d.ts +1 -1
  48. package/dist/deployment/release/runtime.d.ts +0 -2
  49. package/dist/deployment/release/runtime.js +0 -2
  50. package/dist/deployment/release/served/index.d.ts +1 -2
  51. package/dist/deployment/release/served/index.js +7 -3
  52. package/dist/deployment/release/served/views.js +0 -1
  53. package/dist/deployment/verify/index.d.ts +2 -4
  54. package/dist/deployment/verify/index.js +1 -3
  55. package/dist/deployment/verify/preflight/index.d.ts +0 -12
  56. package/dist/deployment/verify/preflight/index.js +0 -12
  57. package/dist/deployment/verify/readiness/index.d.ts +2 -6
  58. package/dist/deployment/verify/readiness/index.js +3 -12
  59. package/dist/deployment/worker/response.d.ts +1 -4
  60. package/dist/deployment/worker/response.js +2 -8
  61. package/dist/execution/identity/authentication.d.ts +10 -1
  62. package/dist/execution/identity/authentication.js +21 -0
  63. package/dist/execution/identity/delivery.d.ts +2 -7
  64. package/dist/execution/identity/delivery.js +1 -23
  65. package/dist/execution/identity/identity.d.ts +2 -3
  66. package/dist/execution/identity/identity.js +5 -1
  67. package/dist/execution/index.d.ts +1 -3
  68. package/dist/execution/index.js +1 -2
  69. package/dist/execution/invocation/admission/authentication.d.ts +8 -5
  70. package/dist/execution/invocation/admission/authentication.js +39 -21
  71. package/dist/execution/invocation/admission/authority.d.ts +21 -6
  72. package/dist/execution/invocation/admission/authority.js +6 -4
  73. package/dist/execution/invocation/admission/index.d.ts +2 -2
  74. package/dist/execution/invocation/admission/index.js +1 -1
  75. package/dist/execution/invocation/dependency/bind.d.ts +2 -0
  76. package/dist/execution/invocation/dependency/bind.js +1 -2
  77. package/dist/execution/invocation/dispatch/context.d.ts +5 -5
  78. package/dist/execution/invocation/dispatch/context.js +16 -30
  79. package/dist/execution/invocation/dispatch/workflow.js +0 -4
  80. package/dist/execution/invocation/index.d.ts +2 -2
  81. package/dist/execution/invocation/index.js +1 -1
  82. package/dist/execution/invocation/integration/call.d.ts +2 -1
  83. package/dist/execution/invocation/integration/call.js +1 -1
  84. package/dist/execution/invocation/integration/clients.d.ts +1 -1
  85. package/dist/execution/invocation/invocation.js +3 -12
  86. package/dist/execution/invocation/result/errors.d.ts +0 -10
  87. package/dist/execution/invocation/result/errors.js +0 -17
  88. package/dist/execution/invocation/result/index.d.ts +2 -2
  89. package/dist/execution/invocation/result/index.js +1 -1
  90. package/dist/execution/runtime/release.d.ts +6 -11
  91. package/dist/execution/runtime/release.js +2 -9
  92. package/dist/execution/service/create.js +3 -1
  93. package/dist/execution/service/service.d.ts +2 -3
  94. package/dist/execution/service/serving/delivery.d.ts +1 -2
  95. package/dist/execution/service/serving/delivery.js +1 -2
  96. package/dist/execution/service/serving/source.d.ts +3 -10
  97. package/dist/execution/service/serving/source.js +1 -5
  98. package/dist/execution/workflows/index.d.ts +1 -1
  99. package/dist/execution/workflows/index.js +1 -1
  100. package/dist/execution/workflows/options.d.ts +0 -6
  101. package/dist/execution/workflows/options.js +0 -18
  102. package/dist/execution/workflows/receiver.d.ts +1 -2
  103. package/dist/execution/workflows/receiver.js +13 -20
  104. package/dist/execution/workflows/route.d.ts +1 -3
  105. package/dist/execution/workflows/route.js +4 -9
  106. package/dist/execution/workflows/run.d.ts +1 -1
  107. package/dist/execution/workflows/run.js +1 -1
  108. package/dist/index.d.ts +1 -1
  109. package/dist/index.js +1 -1
  110. package/dist/platform/graph/alias.d.ts +1 -5
  111. package/dist/platform/graph/alias.js +1 -5
  112. package/dist/platform/graph/document/index.d.ts +1 -1
  113. package/dist/platform/graph/document/index.js +1 -1
  114. package/dist/platform/graph/index.d.ts +1 -1
  115. package/dist/platform/graph/index.js +1 -1
  116. package/dist/platform/release/index.d.ts +1 -26
  117. package/dist/platform/release/index.js +1 -26
  118. package/dist/platform/schema/class-icon-svg.d.ts +9 -0
  119. package/dist/platform/schema/class-icon-svg.js +29 -0
  120. package/dist/platform/schema/class-icon.d.ts +3 -8
  121. package/dist/platform/schema/class-icon.js +2 -29
  122. package/dist/platform/schema/index.d.ts +1 -1
  123. package/dist/platform/schema/schema-authoring.d.ts +14 -7
  124. package/dist/platform/schema/schema-authoring.js +5 -1
  125. package/dist/project/admit.js +0 -4
  126. package/dist/project/install-command.d.ts +0 -4
  127. package/dist/project/install-command.js +1 -5
  128. package/dist/tooling/cli/deploy-mode.d.ts +3 -59
  129. package/dist/tooling/cli/deploy-mode.js +46 -122
  130. package/dist/tooling/cli/deploy-result.d.ts +10 -15
  131. package/dist/tooling/cli/help.js +9 -16
  132. package/dist/tooling/cli/immutable-deployment.d.ts +3 -3
  133. package/dist/tooling/cli/index.d.ts +1 -1
  134. package/dist/tooling/cli/list.d.ts +5 -7
  135. package/dist/tooling/cli/list.js +9 -61
  136. package/dist/tooling/cli/orchestrate.js +6 -16
  137. package/dist/tooling/cli/publish/index.d.ts +2 -2
  138. package/dist/tooling/cli/registry/client.js +1 -1
  139. package/dist/tooling/cli/secrets.d.ts +2 -2
  140. package/dist/tooling/linter/implementations/source/global.js +0 -1
  141. package/dist/tooling/linter/implementations/source/verifiers.js +0 -2
  142. package/dist/tooling/linter/policy/generated.js +2 -51
  143. package/dist/tooling/linter/requirements/registry.js +0 -6
  144. package/package.json +9 -8
  145. package/dist/application/query/execution/projection.d.ts +0 -3
  146. package/dist/application/query/execution/projection.js +0 -3
  147. package/dist/deployment/adapter/legacy/adapter.d.ts +0 -40
  148. package/dist/deployment/adapter/legacy/adapter.js +0 -1
  149. package/dist/deployment/adapter/legacy/deploy/context.d.ts +0 -19
  150. package/dist/deployment/adapter/legacy/deploy/context.js +0 -1
  151. package/dist/deployment/adapter/legacy/deploy/index.d.ts +0 -2
  152. package/dist/deployment/adapter/legacy/deploy/index.js +0 -1
  153. package/dist/deployment/adapter/legacy/deploy/result.d.ts +0 -89
  154. package/dist/deployment/adapter/legacy/deploy/result.js +0 -1
  155. package/dist/deployment/adapter/legacy/index.d.ts +0 -24
  156. package/dist/deployment/adapter/legacy/index.js +0 -1
  157. package/dist/deployment/adapter/legacy/prepare/artifact.d.ts +0 -43
  158. package/dist/deployment/adapter/legacy/prepare/artifact.js +0 -1
  159. package/dist/deployment/adapter/legacy/prepare/context.d.ts +0 -33
  160. package/dist/deployment/adapter/legacy/prepare/context.js +0 -1
  161. package/dist/deployment/adapter/legacy/prepare/index.d.ts +0 -2
  162. package/dist/deployment/adapter/legacy/prepare/index.js +0 -1
  163. package/dist/deployment/deploy.d.ts +0 -20
  164. package/dist/deployment/deploy.js +0 -31
  165. package/dist/deployment/release/legacy/admission.d.ts +0 -3
  166. package/dist/deployment/release/legacy/admission.js +0 -8
  167. package/dist/deployment/release/legacy/assemble.d.ts +0 -5
  168. package/dist/deployment/release/legacy/assemble.js +0 -20
  169. package/dist/deployment/release/legacy/index.d.ts +0 -35
  170. package/dist/deployment/release/legacy/index.js +0 -34
  171. package/dist/deployment/release/legacy/release.d.ts +0 -12
  172. package/dist/deployment/release/legacy/release.js +0 -1
  173. package/dist/deployment/release/legacy/seal.d.ts +0 -10
  174. package/dist/deployment/release/legacy/seal.js +0 -17
  175. package/dist/deployment/verify/preflight/artifact.d.ts +0 -6
  176. package/dist/deployment/verify/preflight/artifact.js +0 -122
  177. package/dist/deployment/verify/preflight/publication.d.ts +0 -4
  178. package/dist/deployment/verify/preflight/publication.js +0 -15
  179. package/dist/deployment/verify/readiness/deployment.d.ts +0 -3
  180. package/dist/deployment/verify/readiness/deployment.js +0 -143
  181. package/dist/deployment/verify/readiness/legacy/index.d.ts +0 -2
  182. package/dist/deployment/verify/readiness/legacy/index.js +0 -2
  183. package/dist/deployment/verify/readiness/legacy/publication.d.ts +0 -12
  184. package/dist/deployment/verify/readiness/legacy/publication.js +0 -23
  185. package/dist/execution/service/errors.d.ts +0 -3
  186. package/dist/execution/service/errors.js +0 -3
  187. package/dist/execution/service/serving/legacy/index.d.ts +0 -15
  188. package/dist/execution/service/serving/legacy/index.js +0 -19
  189. package/dist/tooling/cli/deprecations.d.ts +0 -9
  190. package/dist/tooling/cli/deprecations.js +0 -15
  191. package/dist/tooling/cli/legacy/deploy-result.d.ts +0 -28
  192. package/dist/tooling/cli/legacy/deploy-result.js +0 -37
  193. package/dist/tooling/cli/legacy/stable-target-adapter.d.ts +0 -21
  194. package/dist/tooling/cli/legacy/stable-target-adapter.js +0 -14
  195. package/dist/tooling/cli/legacy/stable-target-deploy.d.ts +0 -40
  196. package/dist/tooling/cli/legacy/stable-target-deploy.js +0 -102
  197. package/dist/tooling/cli/legacy/uploaded-build.d.ts +0 -11
  198. package/dist/tooling/cli/legacy/uploaded-build.js +0 -22
  199. package/dist/tooling/linter/implementations/source/migrations.d.ts +0 -2
  200. package/dist/tooling/linter/implementations/source/migrations.js +0 -113
  201. package/dist/tooling/linter/qualification/index.d.ts +0 -10
  202. package/dist/tooling/linter/qualification/index.js +0 -2
  203. package/dist/tooling/linter/qualification/query-fixtures.d.ts +0 -2
  204. package/dist/tooling/linter/qualification/query-fixtures.js +0 -68
  205. package/dist/tooling/linter/qualification/runner.d.ts +0 -3
  206. package/dist/tooling/linter/qualification/runner.js +0 -6
@@ -1,6 +1,5 @@
1
1
  import type { DeploymentConfiguration } from '../address/index.js';
2
2
  import type { Bundler } from './bundle/index.js';
3
- import type { ArtifactSource, DeployContext, DeployResult, PrepareContext } from './legacy/index.js';
4
3
  import type { AdapterCommand, ConfigureContext, ListContext, ListedDeployment, Placement, PlacementContext, ReleaseDeployContext, ReleaseDeployResult, RetainContext } from './release/index.js';
5
4
  /** What `admit` receives when `defineProject` binds an adapter to one Environment. */
6
5
  export interface AdapterEnvironmentContext {
@@ -12,8 +11,6 @@ export interface AdapterEnvironmentContext {
12
11
  * deploys one sealed release as one immutable deployment, created or reused. It never installs:
13
12
  * `astrale domain install <url>` installs a deployment by its URL.
14
13
  *
15
- * `prepare` and `deploy` remain only for an adapter that also serves Environments on the legacy
16
- * direct-mode path (CT33); an adapter declares both or neither.
17
14
  */
18
15
  export interface Adapter<Parameters extends object = object> {
19
16
  readonly kind: 'adapter';
@@ -43,7 +40,7 @@ export interface Adapter<Parameters extends object = object> {
43
40
  list?(parameters: Parameters, context: ListContext): Promise<readonly ListedDeployment[]>;
44
41
  /**
45
42
  * Keep one published deployment where the host has no registry principal to mark it (a platform
46
- * namespace). Called only after its Publication commits. Rejects with a `RetainRefusal` when the
43
+ * namespace). Called only after its registry publication commits. Rejects with a `RetainRefusal` when the
47
44
  * host can no longer keep it (absent or retired), which no rerun changes; any other rejection is
48
45
  * transient. Absent: the registry marks it (Admin's Services).
49
46
  */
@@ -54,17 +51,7 @@ export interface Adapter<Parameters extends object = object> {
54
51
  * host on the operator's own account). Every effect is the adapter's; the CLI only routes.
55
52
  */
56
53
  readonly commands?: Readonly<Record<string, AdapterCommand<Parameters>>>;
57
- /**
58
- * @deprecated Legacy direct-mode path (CT33) only: place a build at a stable target. Replacement:
59
- * `bundler`, `configure` and `placement`. Deleted with the legacy path (D10).
60
- */
61
- prepare?(parameters: Parameters, context: PrepareContext): Promise<ArtifactSource>;
62
- /**
63
- * @deprecated Legacy direct-mode path (CT33) only: replace a stable target's code in place.
64
- * Replacement: `deployRelease`. Deleted with the legacy path (D10).
65
- */
66
- deploy?(parameters: Parameters, context: DeployContext): Promise<DeployResult>;
67
- readonly secretsFile?: (parameters: Parameters) => string | undefined;
54
+ secretsFile?(parameters: Parameters): string | undefined;
68
55
  }
69
56
  /** What `defineAdapter` admits for an `Adapter` (adapter interface v2). */
70
57
  export interface AdapterInput<Parameters extends object> {
@@ -78,9 +65,5 @@ export interface AdapterInput<Parameters extends object> {
78
65
  list?(parameters: Parameters, context: ListContext): Promise<readonly ListedDeployment[]>;
79
66
  retain?(parameters: Parameters, context: RetainContext): Promise<void>;
80
67
  readonly commands?: Readonly<Record<string, AdapterCommand<Parameters>>>;
81
- /** @deprecated Legacy direct-mode path (CT33) only. Replacement: `configure`, `placement`. */
82
- prepare?(parameters: Parameters, context: PrepareContext): Promise<ArtifactSource>;
83
- /** @deprecated Legacy direct-mode path (CT33) only. Replacement: `deployRelease`. */
84
- deploy?(parameters: Parameters, context: DeployContext): Promise<DeployResult>;
85
- readonly secretsFile?: (parameters: Parameters) => string | undefined;
68
+ secretsFile?(parameters: Parameters): string | undefined;
86
69
  }
@@ -1,4 +1,4 @@
1
- /** One file a bundler or a legacy preparation produced, before admission. */
1
+ /** One file a bundler produced, before admission. */
2
2
  export interface ArtifactFile {
3
3
  readonly path: string;
4
4
  readonly content: Uint8Array;
@@ -1,29 +1,8 @@
1
1
  import type { Deployment } from '../deployment.js';
2
2
  import type { Adapter, AdapterInput } from './adapter.js';
3
- import type { LegacyAdapter, LegacyAdapterInput } from './legacy/index.js';
4
- /**
5
- * Capture one receiver-bound provider adapter (adapter interface v2): a required `bundler`,
6
- * `configure`, `placement` and `deployRelease`, optionally `list`, `retain` and provider `commands`, and `prepare` with
7
- * `deploy` only while it also serves the legacy direct-mode path.
8
- */
3
+ /** Capture one receiver-bound adapter that deploys immutable DomainRelease v4 deployments. */
9
4
  export declare function defineAdapter<Parameters extends object>(input: AdapterInput<Parameters>): Adapter<Parameters>;
10
- /**
11
- * Capture one receiver-bound adapter on the contract before interface v2: its required `bundler`,
12
- * `prepare` and `deploy`.
13
- *
14
- * @deprecated Every Environment such an adapter deploys is on the legacy direct-mode path (CT33).
15
- * Declare adapter interface v2 instead: `configure`, `placement` and `deployRelease` beside the
16
- * same `bundler`.
17
- */
18
- export declare function defineAdapter<Parameters extends object>(input: LegacyAdapterInput<Parameters>): LegacyAdapter<Parameters>;
19
- /** Bind one provider adapter to the parameters of one Project Environment. */
5
+ /** Bind one admitted adapter to the parameters of one Project Environment. */
20
6
  export declare function defineDeployment<const Parameters extends object>(adapter: Adapter<Parameters>, parameters: Parameters): Deployment<Parameters, Adapter<Parameters>>;
21
- /**
22
- * Bind one adapter on the contract before interface v2 to the parameters of one Environment.
23
- *
24
- * @deprecated The Environment is on the legacy direct-mode path (CT33). Replacement: an adapter
25
- * that implements adapter interface v2.
26
- */
27
- export declare function defineDeployment<const Parameters extends object>(adapter: LegacyAdapter<Parameters>, parameters: Parameters): Deployment<Parameters, LegacyAdapter<Parameters>>;
28
- /** Whether `defineAdapter` admitted this value, on either contract. */
29
- export declare function isAdapter(input: unknown): input is Adapter | LegacyAdapter;
7
+ /** Whether defineAdapter admitted this immutable-deployment adapter. */
8
+ export declare function isAdapter(input: unknown): input is Adapter;
@@ -1,7 +1,7 @@
1
1
  import { captureDeployment } from '../deployment.js';
2
2
  const admittedAdapters = new WeakSet();
3
3
  const admittedBundlers = new WeakMap();
4
- /** Every field an adapter definition may declare, in either contract. */
4
+ /** Every field an immutable-deployment adapter may declare. */
5
5
  const FIELDS = [
6
6
  'name',
7
7
  'version',
@@ -13,46 +13,29 @@ const FIELDS = [
13
13
  'list',
14
14
  'retain',
15
15
  'commands',
16
- 'prepare',
17
- 'deploy',
18
16
  'secretsFile',
19
17
  ];
20
- /** The operations that make a definition adapter interface v2. */
21
18
  const RELEASE_OPERATIONS = ['configure', 'placement', 'deployRelease'];
22
- const OPTIONAL_RELEASE_OPERATIONS = ['list', 'retain'];
23
- /** The operations of the legacy direct-mode path. */
24
- const STABLE_TARGET_OPERATIONS = ['prepare', 'deploy'];
25
- /** Every operation an adapter may declare, in the order an admitted adapter lists them. */
26
- const OPERATIONS = FIELDS.filter((key) => key !== 'name' && key !== 'version' && key !== 'bundler' && key !== 'commands');
27
- /** A provider command name, `astrale-domain <adapter> <command>`, and an option name. */
19
+ const OPERATIONS = ['admit', ...RELEASE_OPERATIONS, 'list', 'retain', 'secretsFile'];
28
20
  const COMMAND_NAME = /^[a-z][a-z0-9-]{0,31}$/u;
21
+ /** Capture one receiver-bound adapter that deploys immutable DomainRelease v4 deployments. */
29
22
  export function defineAdapter(input) {
30
23
  const value = record(input, 'Adapter definition');
31
24
  if (Reflect.ownKeys(value).some((key) => !FIELDS.includes(key))) {
32
25
  invalidFields();
33
26
  }
34
- const declared = (key) => value[key] !== undefined;
35
- const release = [...RELEASE_OPERATIONS, ...OPTIONAL_RELEASE_OPERATIONS].some(declared);
36
- // A legacy definition names both operations, as it always had to; v2 treats undefined as absent.
37
- const stableTarget = STABLE_TARGET_OPERATIONS.filter((key) => release ? declared(key) : Object.hasOwn(value, key));
38
- if (!release && stableTarget.length !== STABLE_TARGET_OPERATIONS.length)
39
- invalidFields();
40
27
  const name = stableName(input.name);
41
28
  const version = stableName(input.version);
42
- if (release)
43
- admitRelease(name, value, stableTarget.length);
29
+ const missing = RELEASE_OPERATIONS.filter((key) => value[key] === undefined);
30
+ if (missing.length > 0) {
31
+ throw new TypeError(`Adapter ${name} must declare ${missing.join(', ')} to deploy immutable releases.`);
32
+ }
44
33
  if (value.bundler === undefined)
45
34
  missingBundler(name);
46
35
  const bundler = admitBundler(input.bundler);
47
36
  const receiver = Object.freeze({ ...input });
48
- const required = new Set([...(release ? RELEASE_OPERATIONS : []), ...stableTarget]);
49
- const operations = Object.fromEntries(OPERATIONS.filter((key) => required.has(key) || declared(key)).map((key) => [
50
- key,
51
- capture(receiver, key),
52
- ]));
53
- if (value.commands !== undefined && !release) {
54
- throw new TypeError(`Adapter ${name} declares commands without adapter interface v2.`);
55
- }
37
+ const operations = Object.fromEntries(OPERATIONS.filter((key) => RELEASE_OPERATIONS.includes(key) ||
38
+ value[key] !== undefined).map((key) => [key, capture(receiver, key)]));
56
39
  const adapter = Object.freeze({
57
40
  kind: 'adapter',
58
41
  name,
@@ -64,22 +47,7 @@ export function defineAdapter(input) {
64
47
  admittedAdapters.add(adapter);
65
48
  return adapter;
66
49
  }
67
- /**
68
- * An adapter interface v2 definition implements configure, placement and deployRelease, and keeps
69
- * prepare with deploy, or neither.
70
- */
71
- function admitRelease(name, value, stableTargetOperations) {
72
- const missing = RELEASE_OPERATIONS.filter((key) => value[key] === undefined);
73
- if (missing.length > 0) {
74
- throw new TypeError(`Adapter ${name} declares part of adapter interface v2 without ${missing.join(', ')}: ` +
75
- 'an adapter that deploys immutable deployments implements configure, placement and ' +
76
- 'deployRelease.');
77
- }
78
- if (stableTargetOperations === 1) {
79
- throw new TypeError(`Adapter ${name} declares only one of prepare and deploy: an adapter that keeps the legacy ` +
80
- 'direct-mode path declares both.');
81
- }
82
- }
50
+ /** Bind one admitted adapter to the parameters of one Project Environment. */
83
51
  export function defineDeployment(adapter, parameters) {
84
52
  if (!isAdapter(adapter))
85
53
  throw new TypeError('Deployment Adapter is not admitted.');
@@ -88,7 +56,7 @@ export function defineDeployment(adapter, parameters) {
88
56
  }
89
57
  return captureDeployment(adapter, Object.freeze({ ...parameters }));
90
58
  }
91
- /** Whether `defineAdapter` admitted this value, on either contract. */
59
+ /** Whether defineAdapter admitted this immutable-deployment adapter. */
92
60
  export function isAdapter(input) {
93
61
  return input !== null && typeof input === 'object' && admittedAdapters.has(input);
94
62
  }
@@ -130,7 +98,7 @@ function record(input, label) {
130
98
  }
131
99
  return input;
132
100
  }
133
- /** Every adapter, on either contract, declares the bundler of the bytes it deploys. */
101
+ /** Every adapter declares the bundler of the bytes it deploys. */
134
102
  function missingBundler(name) {
135
103
  throw new TypeError(`Adapter ${name} declares no bundler. ` +
136
104
  'Every adapter declares `bundler`: the bundler of the environment-free bytes ' +
@@ -3,5 +3,3 @@ export { defineAdapter, defineDeployment, isAdapter } from './define.js';
3
3
  export { RetainRefusal } from './release/refusal.js';
4
4
  export type * from './bundle/index.js';
5
5
  export type * from './release/index.js';
6
- /** @deprecated The contract before adapter interface v2; see `./legacy/index.ts`. */
7
- export type * from './legacy/index.js';
@@ -31,8 +31,7 @@ export type DeploymentCallTarget = {
31
31
  * host stores it, and where it is called. Admin's Services keeps every deployment until it is
32
32
  * retired and counts no call: its deployments are `published` and `withdrawn` once retiring. A
33
33
  * Cloudflare dispatch namespace keeps no retention: its rows carry none, and carry their creation
34
- * instant and key only while their script exists. No first-party adapter reports a last call or an
35
- * expiry any more; the CLI still prints one an older adapter reports.
34
+ * instant and key only while their script exists. Deployments have no last-call or expiry clock.
36
35
  *
37
36
  * The adapter does not admit the record. The listing admits it with `acceptDeploymentRecord`, and a
38
37
  * record it refuses (one a host on an older SDK still admits, say) never fails the listing: that
@@ -18,16 +18,12 @@ export interface DeploymentSummaryV1 {
18
18
  * `published` on Admin's Services, which keeps every deployment until it is retired. Absent on a
19
19
  * dispatch namespace, which keeps no retention.
20
20
  */
21
- readonly retention?: 'preview' | 'published';
21
+ readonly retention?: 'published';
22
22
  /** When the host created it; absent when the host no longer knows (its script is gone). */
23
23
  readonly createdAt?: string;
24
- /** An older adapter's report of the last call; no first-party adapter reports it any more. */
25
- readonly lastCallAt?: string;
26
- /** An older adapter's preview expiry; no first-party adapter reports it any more. */
27
- readonly expiresAt?: string;
28
24
  readonly retiredAt?: string;
29
- /** `withdrawn` once its owner retired it (`expired` only from an older adapter). */
30
- readonly retirement?: 'expired' | 'withdrawn';
25
+ /** `withdrawn` once its owner retired it. */
26
+ readonly retirement?: 'withdrawn';
31
27
  /** The RFC 7638 thumbprint of its key; absent when the host no longer knows (its script is gone). */
32
28
  readonly signingKeyId?: string;
33
29
  readonly record: DeploymentRecordV1;
@@ -1,5 +1,3 @@
1
- export { deploy } from './deploy.js';
2
- export type { DeploymentInput, LegacyDeployment } from './deploy.js';
3
1
  export type { Deployment } from './deployment.js';
4
2
  export { runtime } from './runtime/index.js';
5
3
  export type { RuntimeReference } from './runtime/index.js';
@@ -1,2 +1 @@
1
- export { deploy } from './deploy.js';
2
1
  export { runtime } from './runtime/index.js';
@@ -10,4 +10,10 @@ export interface Build<Schema extends schema.DomainSchema = schema.DomainSchema,
10
10
  readonly requirements: release.Requirements;
11
11
  readonly routes: routes.Plan;
12
12
  readonly frontend?: FrontendCompilation;
13
+ /** What the release manifest shows of the application: its icon. */
14
+ readonly presentation?: BuildPresentation;
15
+ }
16
+ export interface BuildPresentation {
17
+ /** One self-contained inline SVG. */
18
+ readonly icon?: string;
13
19
  }
@@ -19,6 +19,7 @@ export function compile(definition) {
19
19
  const compiled = schemaApi.compile(definition.schema);
20
20
  const requirements = compileRequirements(domain, definition.requirements, sourceBundle);
21
21
  const frontend = compileFrontend(definition.frontend, domain);
22
+ const presentation = definition.icon === undefined ? undefined : Object.freeze({ icon: definition.icon });
22
23
  const plan = routes.compile({
23
24
  domain,
24
25
  routes: admitRoutes(definition.routes, registry),
@@ -37,6 +38,7 @@ export function compile(definition) {
37
38
  requirements,
38
39
  routes: plan,
39
40
  ...(frontend === undefined ? {} : { frontend }),
41
+ ...(presentation === undefined ? {} : { presentation }),
40
42
  });
41
43
  return admitBuild(build, { domain, registry });
42
44
  }
@@ -1,19 +1,17 @@
1
1
  import type { Frontend, FrontendSource } from '../../../application/view/index.js';
2
- import type { FrontendHandshake, IframeRequirements, ViewHostRequirements } from '../../../application/view/index.js';
3
- import type { Key, ViewRef } from '../../../platform/schema/index.js';
2
+ import type { FrontendHandshake, ViewHostRequirements } from '../../../application/view/index.js';
3
+ import type { Key } from '../../../platform/schema/index.js';
4
4
  import type { Domain } from '../../../platform/schema/index.js';
5
5
  export interface CompiledFrontendRoute {
6
6
  readonly view: Key.View;
7
7
  readonly path: string;
8
8
  readonly document: string;
9
9
  readonly handshake: FrontendHandshake;
10
- readonly iframe?: IframeRequirements;
11
10
  readonly host?: ViewHostRequirements;
12
11
  }
13
12
  export interface FrontendCompilation {
14
13
  readonly source: FrontendSource;
15
14
  readonly routes: readonly CompiledFrontendRoute[];
16
- readonly entrypoint: ViewRef;
17
15
  }
18
16
  /** Lower exact authored View names to canonical DSL references without placing URLs. */
19
17
  export declare function compileFrontend(frontend: Frontend | undefined, domain: Domain): FrontendCompilation | undefined;
@@ -15,16 +15,11 @@ export function compileFrontend(frontend, domain) {
15
15
  path: route.path,
16
16
  document: route.document,
17
17
  handshake: route.handshake,
18
- ...(route.iframe === undefined ? {} : { iframe: route.iframe }),
19
18
  ...(route.host === undefined ? {} : { host: route.host }),
20
19
  });
21
20
  });
22
- const entrypoint = domain.views[frontend.entrypoint];
23
- if (entrypoint === undefined)
24
- throw new TypeError('Frontend entrypoint is absent from its Domain.');
25
21
  return Object.freeze({
26
22
  source: frontend.source,
27
23
  routes: Object.freeze(routes),
28
- entrypoint: entrypoint.ref,
29
24
  });
30
25
  }
@@ -3,11 +3,7 @@ const MEDIA_TYPE = 'application/vnd.astrale.frontend-material+octet-stream;v=1';
3
3
  export function digest(frontend, files) {
4
4
  const encoder = new TextEncoder();
5
5
  const chunks = [
6
- encoder.encode(JSON.stringify({
7
- source: frontend.source,
8
- routes: frontend.routes,
9
- entrypoint: frontend.entrypoint,
10
- })),
6
+ encoder.encode(JSON.stringify({ source: frontend.source, routes: frontend.routes })),
11
7
  ];
12
8
  for (const file of files) {
13
9
  const bytes = file.bytes();
@@ -1,6 +1,6 @@
1
1
  import type { DomainSchema } from '@astrale-os/kernel-dsl/v1/schema';
2
2
  import type { Runtime } from '../../application/runtime/index.js';
3
- import type { Build } from './build.js';
3
+ import type { Build, BuildPresentation } from './build.js';
4
4
  import type { FrontendCompilation } from './frontend/index.js';
5
5
  export interface BuildMaterial {
6
6
  readonly format: 'astrale.sdk.build-material';
@@ -16,6 +16,7 @@ export interface BuildMaterial {
16
16
  readonly requirements: Build['requirements'];
17
17
  readonly routes: Build['routes'];
18
18
  readonly frontend?: FrontendCompilation;
19
+ readonly presentation?: BuildPresentation;
19
20
  }
20
21
  declare const GENERATED_BUILD_MATERIAL: unique symbol;
21
22
  /** Exact Build material embedded by an Astrale execution-code generator. */
@@ -23,7 +24,6 @@ export interface GeneratedBuildMaterial {
23
24
  readonly format: 'astrale.sdk.generated-build-material';
24
25
  readonly version: 1;
25
26
  readonly material: BuildMaterial;
26
- readonly digest: Build['schema']['bundle']['ref']['digest'];
27
27
  readonly [GENERATED_BUILD_MATERIAL]: 'generated-build-material';
28
28
  }
29
29
  /** Detach the provider-neutral, runtime-free material embedded into generated execution code. */
@@ -4,10 +4,11 @@ import { load as loadCompiledSchema } from '@astrale-os/kernel-dsl/v1/compiled/l
4
4
  import { revision } from '@astrale-os/kernel-dsl/v1/schema/revision';
5
5
  import { equal } from '@astrale-os/kernel-dsl/value';
6
6
  import * as artifact from '@astrale-os/kernel-protocol/artifact';
7
- import { BUNDLE_MEDIA_TYPE } from '@astrale-os/kernel-protocol/release/bundle';
8
- import { admitRequirements, validateRequirements, } from '@astrale-os/kernel-protocol/release/requirements';
7
+ import { BUNDLE_MEDIA_TYPE } from '@astrale-os/kernel-protocol/release';
8
+ import { admitRequirements, validateRequirements } from '@astrale-os/kernel-protocol/release';
9
9
  import * as routes from '@astrale-os/kernel-protocol/routes';
10
10
  import { admitRuntimeRegistry, isRuntime } from '../../application/runtime/index.js';
11
+ import { admitClassIconSvg } from '../../platform/schema/class-icon-svg.js';
11
12
  import { admitBuild, isBuild } from './admission.js';
12
13
  /** Detach the provider-neutral, runtime-free material embedded into generated execution code. */
13
14
  export function material(build) {
@@ -29,6 +30,7 @@ export function material(build) {
29
30
  requirements: build.requirements,
30
31
  routes: build.routes,
31
32
  ...(build.frontend === undefined ? {} : { frontend: build.frontend }),
33
+ ...(build.presentation === undefined ? {} : { presentation: build.presentation }),
32
34
  });
33
35
  }
34
36
  /** Produce opaque material for execution code from one admitted Build. */
@@ -38,7 +40,6 @@ export function generatedMaterial(build) {
38
40
  format: 'astrale.sdk.generated-build-material',
39
41
  version: 1,
40
42
  material: value,
41
- digest: digestOf(value),
42
43
  });
43
44
  }
44
45
  /** Re-admit detached provider-neutral Build material against the exact Runtime value. */
@@ -62,6 +63,7 @@ export function restoreBuild(input, runtime) {
62
63
  const compiled = deepFreeze(input.schema.compiled);
63
64
  const bundleRef = deepFreeze(input.schema.bundle.ref);
64
65
  const frontend = input.frontend === undefined ? undefined : deepFreeze(input.frontend);
66
+ const presentation = input.presentation === undefined ? undefined : admitPresentation(input.presentation);
65
67
  const detached = new Uint8Array(bytes);
66
68
  const build = Object.freeze({
67
69
  kind: 'build',
@@ -77,6 +79,7 @@ export function restoreBuild(input, runtime) {
77
79
  requirements,
78
80
  routes: plan,
79
81
  ...(frontend === undefined ? {} : { frontend }),
82
+ ...(presentation === undefined ? {} : { presentation }),
80
83
  });
81
84
  return admitBuild(build, { domain, registry });
82
85
  }
@@ -106,6 +109,7 @@ export function restoreGeneratedBuild(input, runtime) {
106
109
  requirements: material.requirements,
107
110
  routes: material.routes,
108
111
  ...(material.frontend === undefined ? {} : { frontend: material.frontend }),
112
+ ...(material.presentation === undefined ? {} : { presentation: material.presentation }),
109
113
  });
110
114
  return admitBuild(build, { domain, registry });
111
115
  }
@@ -118,7 +122,7 @@ function acceptGeneratedMaterial(input, runtime) {
118
122
  Array.isArray(input) ||
119
123
  format !== 'astrale.sdk.generated-build-material' ||
120
124
  version !== 1 ||
121
- Reflect.ownKeys(input).some((key) => key !== 'format' && key !== 'version' && key !== 'material' && key !== 'digest')) {
125
+ Reflect.ownKeys(input).some((key) => key !== 'format' && key !== 'version' && key !== 'material')) {
122
126
  invalid();
123
127
  }
124
128
  assertMaterialEnvelope(material, runtime);
@@ -128,14 +132,6 @@ function acceptGeneratedMaterial(input, runtime) {
128
132
  deepFreeze(input);
129
133
  return Object.freeze({ material });
130
134
  }
131
- function digestOf(input) {
132
- try {
133
- return artifact.identify(new TextEncoder().encode(JSON.stringify(input)), 'application/vnd.astrale.sdk.build-material+json').digest;
134
- }
135
- catch {
136
- invalid();
137
- }
138
- }
139
135
  function assertMaterialEnvelope(input, runtime) {
140
136
  if (!isRuntime(runtime))
141
137
  throw new TypeError('Build Runtime is not admitted.');
@@ -150,7 +146,8 @@ function assertMaterialEnvelope(input, runtime) {
150
146
  key !== 'callables' &&
151
147
  key !== 'requirements' &&
152
148
  key !== 'routes' &&
153
- key !== 'frontend')) {
149
+ key !== 'frontend' &&
150
+ key !== 'presentation')) {
154
151
  invalid();
155
152
  }
156
153
  }
@@ -186,6 +183,24 @@ function admitRoutePlan(input, domain) {
186
183
  invalid();
187
184
  return admitted;
188
185
  }
186
+ /** External material must re-admit its icon using the same worker-safe SVG owner as authoring. */
187
+ function admitPresentation(input) {
188
+ if (input === null || typeof input !== 'object' || Array.isArray(input))
189
+ invalid();
190
+ const value = input;
191
+ if (Reflect.ownKeys(value).some((key) => key !== 'icon'))
192
+ invalid();
193
+ const { icon } = value;
194
+ if (icon === undefined)
195
+ return Object.freeze({});
196
+ if (typeof icon !== 'string')
197
+ invalid();
198
+ const admitted = admitClassIconSvg(icon);
199
+ // Material carries an exact admitted value, rather than authored text to normalize.
200
+ if (admitted !== icon)
201
+ invalid();
202
+ return Object.freeze({ icon: admitted });
203
+ }
189
204
  function deepFreeze(input, seen = new WeakSet()) {
190
205
  if (input !== null && typeof input === 'object' && !seen.has(input)) {
191
206
  seen.add(input);
@@ -1,14 +1,10 @@
1
- import type { Adapter, LegacyAdapter } from './adapter/index.js';
2
- /**
3
- * One adapter bound to the parameters of one Project Environment. `AdapterValue` is an adapter
4
- * interface v2 `Adapter`, or a `@deprecated` `LegacyAdapter` whose Environments are all on the
5
- * legacy direct-mode path (CT33).
6
- */
7
- export interface Deployment<Parameters extends object = object, AdapterValue extends Adapter<Parameters> | LegacyAdapter<Parameters> = Adapter<Parameters> | LegacyAdapter<Parameters>> {
1
+ import type { Adapter } from './adapter/index.js';
2
+ /** One immutable-deployment adapter bound to one Project Environment. */
3
+ export interface Deployment<Parameters extends object = object, AdapterValue extends Adapter<Parameters> = Adapter<Parameters>> {
8
4
  readonly kind: 'deployment';
9
5
  readonly adapter: AdapterValue;
10
6
  readonly parameters: Parameters;
11
7
  }
12
8
  /** Internal adapter binding boundary used by public provider packages. */
13
- export declare function captureDeployment<const Parameters extends object>(adapter: Adapter<Parameters> | LegacyAdapter<Parameters>, parameters: Parameters): Deployment<Parameters>;
9
+ export declare function captureDeployment<const Parameters extends object>(adapter: Adapter<Parameters>, parameters: Parameters): Deployment<Parameters>;
14
10
  export declare function isDeployment(input: unknown): input is Deployment;
@@ -1,14 +1,12 @@
1
1
  export { defineAdapter, defineDeployment, isAdapter } from './adapter/index.js';
2
- export type { Adapter, AdapterCommand, AdapterCommandContext, AdapterCommandResult, AdapterEnvironmentContext, AdapterInput, AddressingPlan, ArtifactFile, ArtifactSource, Bundle, BundleContext, Bundler, BundleSource, ConfigureContext, DeployContext, DeploymentCallTarget, DeploymentPhase, DeploymentProgress, DeploymentSecretsState, DeployResult, FailedDeployResult, FailedReleaseDeployResult, LegacyAdapter, LegacyAdapterInput, ListContext, ListedDeployment, MutationKnowledge, Placement, PlacementContext, PreparedArtifact, PreparedArtifactFile, PrepareContext, ReadyDeployResult, ReadyReleaseDeployResult, ReleaseDeployContext, ReleaseDeploymentPhase, ReleaseDeployResult, RetainContext, } from './adapter/index.js';
2
+ export type { Adapter, AdapterCommand, AdapterCommandContext, AdapterCommandResult, AdapterEnvironmentContext, AdapterInput, ArtifactFile, Bundle, BundleContext, Bundler, BundleSource, ConfigureContext, DeploymentCallTarget, DeploymentSecretsState, FailedReleaseDeployResult, ListContext, ListedDeployment, MutationKnowledge, Placement, PlacementContext, PreparedArtifactFile, ReadyReleaseDeployResult, ReleaseDeployContext, ReleaseDeploymentPhase, ReleaseDeployResult, RetainContext, } from './adapter/index.js';
3
3
  export { compile, isBuild } from './build/index.js';
4
4
  export type { Build, BuildBundle, BuildDigest, BuildManifestV1, BuildSchema, } from './build/index.js';
5
- export { deploy } from './deploy.js';
6
- export type { DeploymentInput, LegacyDeployment } from './deploy.js';
7
5
  export { isDeployment } from './deployment.js';
8
6
  export type { Deployment } from './deployment.js';
9
7
  export { addressing, assemble, isAddressing, isRelease } from './release/index.js';
10
8
  export type { Addressing, Release } from './release/index.js';
11
9
  export { admit as admitRuntime, resolve as resolveRuntime, runtime } from './runtime/index.js';
12
10
  export type { ResolvedRuntimeReference, RuntimeModuleLoader, RuntimeReference, } from './runtime/index.js';
13
- export { verifyBundle, verifyDeployment, verifyPreflight, verifyReadiness, verifyUploadedBuild, } from './verify/index.js';
14
- export type { BundleInput, PreflightInput } from './verify/index.js';
11
+ export { verifyBundle, verifyReadiness, verifyUploadedBuild } from './verify/index.js';
12
+ export type { BundleInput } from './verify/index.js';
@@ -1,7 +1,6 @@
1
1
  export { defineAdapter, defineDeployment, isAdapter } from './adapter/index.js';
2
2
  export { compile, isBuild } from './build/index.js';
3
- export { deploy } from './deploy.js';
4
3
  export { isDeployment } from './deployment.js';
5
4
  export { addressing, assemble, isAddressing, isRelease } from './release/index.js';
6
5
  export { admit as admitRuntime, resolve as resolveRuntime, runtime } from './runtime/index.js';
7
- export { verifyBundle, verifyDeployment, verifyPreflight, verifyReadiness, verifyUploadedBuild, } from './verify/index.js';
6
+ export { verifyBundle, verifyReadiness, verifyUploadedBuild } from './verify/index.js';
@@ -5,15 +5,8 @@ import type { IssuerId } from '../../platform/auth/index.js';
5
5
  */
6
6
  export interface Addressing {
7
7
  readonly issuer: IssuerId;
8
- /** Public origin serving this Release; the issuer can remain on an older deployment. */
8
+ /** Public origin serving this Release, identical to its issuer. */
9
9
  readonly publicUrl: IssuerId;
10
10
  }
11
- export declare function addressing(input: string, options?: {
12
- /**
13
- * @deprecated Stable-target `legacy` path only: adapter-cloudflare direct mode serves under an
14
- * issuer distinct from its route (`identityIssuer`). Removed with that mode at D10; a
15
- * deployment's URL is its issuer.
16
- */
17
- readonly publicUrl?: string;
18
- }): Addressing;
11
+ export declare function addressing(input: string): Addressing;
19
12
  export declare function isAddressing(input: unknown): input is Addressing;
@@ -1,9 +1,8 @@
1
1
  import { issuer } from '../../platform/auth/index.js';
2
2
  const admittedAddressing = new WeakSet();
3
- export function addressing(input, options = {}) {
3
+ export function addressing(input) {
4
4
  const admitted = origin(input);
5
- const publicUrl = options.publicUrl === undefined ? admitted : origin(options.publicUrl);
6
- const value = Object.freeze({ issuer: admitted, publicUrl });
5
+ const value = Object.freeze({ issuer: admitted, publicUrl: admitted });
7
6
  admittedAddressing.add(value);
8
7
  return value;
9
8
  }
@@ -3,5 +3,3 @@ export { capture, isRelease } from './admission.js';
3
3
  export { addressing, isAddressing, type Addressing } from './addressing.js';
4
4
  export { invocationPath } from './invocation.js';
5
5
  export type { Release } from './release.js';
6
- /** @deprecated Stable-target Publication v3; see `legacy/index.ts` for its consumers and removal. */
7
- export * as legacy from './legacy/index.js';
@@ -2,5 +2,3 @@ export { assemble } from './assemble.js';
2
2
  export { capture, isRelease } from './admission.js';
3
3
  export { addressing, isAddressing } from './addressing.js';
4
4
  export { invocationPath } from './invocation.js';
5
- /** @deprecated Stable-target Publication v3; see `legacy/index.ts` for its consumers and removal. */
6
- export * as legacy from './legacy/index.js';
@@ -12,7 +12,7 @@ export interface Release<BuildValue extends Build = Build> {
12
12
  readonly build: BuildValue;
13
13
  /**
14
14
  * The deployment's URL: its origin, which is also its issuer (`document.identity.issuer`). A
15
- * deployment never splits the two; only the stable-target `legacy` path does.
15
+ * deployment binds both to the same immutable URL.
16
16
  */
17
17
  readonly url: IssuerId;
18
18
  readonly document: release.DomainRelease;
@@ -1,4 +1,2 @@
1
1
  export { assemble } from './assemble.js';
2
2
  export { addressing } from './addressing.js';
3
- /** @deprecated Stable-target Publication v3; see `legacy/index.ts` for its consumers and removal. */
4
- export * as legacy from './legacy/index.js';
@@ -1,4 +1,2 @@
1
1
  export { assemble } from './assemble.js';
2
2
  export { addressing } from './addressing.js';
3
- /** @deprecated Stable-target Publication v3; see `legacy/index.ts` for its consumers and removal. */
4
- export * as legacy from './legacy/index.js';
@@ -4,8 +4,7 @@ import type { Addressing } from '../addressing.js';
4
4
  export declare const DELIVERY_PATH: '/install';
5
5
  /**
6
6
  * What a deployment serves beneath its URL: identity, schema bundle, requirements, bindings, routes
7
- * and delivery. A `DomainRelease` v4 adds its build to it, and the v3 Publication of the legacy
8
- * path is exactly this content, so both documents of one build at one address agree.
7
+ * and delivery. A `DomainRelease` v4 adds the digest of its running build.
9
8
  */
10
9
  export type Served = Omit<release.Content, 'format' | 'version' | 'build'>;
11
10
  /** Derive the served content of one exact Build at one Addressing. */
@@ -12,11 +12,15 @@ export function served(build, addressing) {
12
12
  identity: { issuer: addressing.issuer, subject: root.origin },
13
13
  schema: { revision: root.revision, bundle: { href: bundle, ref: build.schema.bundle.ref } },
14
14
  requirements: build.requirements,
15
- ...(build.frontend === undefined
16
- ? {}
17
- : { manifest: Object.freeze({ entrypoint: build.frontend.entrypoint }) }),
15
+ // The root schema declares the Domain name and entrypoint; a release authors neither.
16
+ ...manifest(build),
18
17
  bindings: { callables: callables(build, addressing), views: views(build, addressing) },
19
18
  delivery: release.placeDelivery({ path: DELIVERY_PATH, authentication: { kind: 'public' } }, addressing.publicUrl, bundle),
20
19
  routes: routes(build, addressing),
21
20
  };
22
21
  }
22
+ /** The release manifest carries the Domain icon as `logo`. Absent when the Build carries none. */
23
+ function manifest(build) {
24
+ const { icon } = build.presentation ?? {};
25
+ return icon === undefined ? {} : { manifest: Object.freeze({ logo: icon }) };
26
+ }