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

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.
@@ -16,13 +16,18 @@ export interface PublishCommandInput {
16
16
  readonly json: boolean;
17
17
  readonly signal: AbortSignal;
18
18
  }
19
- /** What `publish` uses of the Domain registry: the index, a baseline's bundle, the Publication. */
20
- type PublishRegistry = Pick<DomainRegistry, 'index' | 'bundle' | 'publish'>;
19
+ /**
20
+ * What `publish` uses of the Domain registry: the index, the claim of an origin no one has, a
21
+ * baseline's bundle, the Publication.
22
+ */
23
+ type PublishRegistry = Pick<DomainRegistry, 'index' | 'claim' | 'bundle' | 'publish'>;
21
24
  export interface PublishCommandDependencies {
22
25
  readonly open: (input: {
23
26
  readonly projectDir: string;
24
27
  readonly identity?: string;
25
28
  readonly signal: AbortSignal;
29
+ /** The first Astrale CLI release that serves every registry command publish may run. */
30
+ readonly minimum?: string;
26
31
  }) => Promise<PublishRegistry>;
27
32
  /** Step 5: the deployment serves exactly this sealed release at its URL. */
28
33
  readonly verify: (release: Release, signal: AbortSignal) => Promise<void>;
@@ -55,7 +60,9 @@ export declare const VERIFY_TIMEOUT_MS = 60000;
55
60
  * configure, placement, label, URL and the sealed release digest.
56
61
  * 1. Read the version from `package.json`.
57
62
  * 2. Read the registry. The version exists: the same release succeeds without effect, another is
58
- * refused. A Domain absent or unreadable, or a registry that does not answer, is refused.
63
+ * refused. An origin the registry does not hold for this identity is claimed: Admin gives an
64
+ * origin no one has to its first claimer, who administers its Domain, and refuses one another
65
+ * account holds. A registry that does not answer is refused.
59
66
  * 3. Judge the version against the highest stable version below it (AM-23); refuse a version
60
67
  * that is too low.
61
68
  * 4. Deploy the release, or reuse its deployment.
@@ -68,6 +75,7 @@ export declare const VERIFY_TIMEOUT_MS = 60000;
68
75
  * keeps the published deployment. No first-party adapter declares it: Admin's Services and a
69
76
  * Cloudflare dispatch namespace keep every deployment until its owner retires it.
70
77
  *
71
- * Steps 0 to 3 make no deploy call. Never installs.
78
+ * Steps 0 to 3 make no deploy call; step 2's claim is the only registry change before step 6.
79
+ * Never installs.
72
80
  */
73
81
  export declare function runPublish(input: PublishCommandInput, dependencies?: PublishCommandDependencies): Promise<number>;
@@ -7,7 +7,7 @@ import { renderDiff } from '../diff/render.js';
7
7
  import { diffReport, publishedSchema } from '../diff/report.js';
8
8
  import { deployPlannedRelease, planImmutableDeployment, runtimeCommit, } from '../immutable-deployment.js';
9
9
  import { DIM, RED, RESET, YELLOW } from '../log.js';
10
- import { RegistryCliError, openDomainRegistry } from '../registry/index.js';
10
+ import { MINIMUM_CLAIM_CLI_VERSION, RegistryCliError, openDomainRegistry, } from '../registry/index.js';
11
11
  import { publishReport } from './report.js';
12
12
  /**
13
13
  * Step 5 reads the deployment's `release.json` (at most 1 MiB) and its Bundle (at most 16 MiB)
@@ -36,7 +36,9 @@ const DEFAULT_DEPENDENCIES = Object.freeze({
36
36
  * configure, placement, label, URL and the sealed release digest.
37
37
  * 1. Read the version from `package.json`.
38
38
  * 2. Read the registry. The version exists: the same release succeeds without effect, another is
39
- * refused. A Domain absent or unreadable, or a registry that does not answer, is refused.
39
+ * refused. An origin the registry does not hold for this identity is claimed: Admin gives an
40
+ * origin no one has to its first claimer, who administers its Domain, and refuses one another
41
+ * account holds. A registry that does not answer is refused.
40
42
  * 3. Judge the version against the highest stable version below it (AM-23); refuse a version
41
43
  * that is too low.
42
44
  * 4. Deploy the release, or reuse its deployment.
@@ -49,7 +51,8 @@ const DEFAULT_DEPENDENCIES = Object.freeze({
49
51
  * keeps the published deployment. No first-party adapter declares it: Admin's Services and a
50
52
  * Cloudflare dispatch namespace keep every deployment until its owner retires it.
51
53
  *
52
- * Steps 0 to 3 make no deploy call. Never installs.
54
+ * Steps 0 to 3 make no deploy call; step 2's claim is the only registry change before step 6.
55
+ * Never installs.
53
56
  */
54
57
  export async function runPublish(input, dependencies = DEFAULT_DEPENDENCIES) {
55
58
  const { build, environment, signal } = input;
@@ -104,7 +107,12 @@ export async function runPublish(input, dependencies = DEFAULT_DEPENDENCIES) {
104
107
  let registry;
105
108
  let index;
106
109
  try {
107
- registry = await dependencies.open({ projectDir: input.projectDir, ...identity, signal });
110
+ registry = await dependencies.open({
111
+ projectDir: input.projectDir,
112
+ ...identity,
113
+ signal,
114
+ minimum: MINIMUM_CLAIM_CLI_VERSION,
115
+ });
108
116
  index = await registry.index(origin);
109
117
  }
110
118
  catch (cause) {
@@ -113,7 +121,18 @@ export async function runPublish(input, dependencies = DEFAULT_DEPENDENCIES) {
113
121
  return refuse(`Domain registry: ${cause.code}: ${cause.message}`, 'Nothing was deployed or published.');
114
122
  }
115
123
  if (index === undefined) {
116
- return refuse(`${origin} is not in the Domain registry, or you may not read it: nothing was deployed.`, 'An administrator of the Admin instance registers the Domain and names who may publish it.');
124
+ // First claim: the registry holds no Domain of this origin for this identity. Admin gives an
125
+ // origin no one has to its first claimer, before anything is deployed.
126
+ try {
127
+ await registry.claim(origin);
128
+ }
129
+ catch (cause) {
130
+ if (!(cause instanceof RegistryCliError))
131
+ throw cause;
132
+ return refuse(...notClaimed(origin, cause));
133
+ }
134
+ progress(`Claimed ${origin} in the Domain registry: this identity administers it.`);
135
+ index = { origin, publications: [] };
117
136
  }
118
137
  const existing = index.publications.find(({ version }) => version === declared);
119
138
  if (existing !== undefined) {
@@ -261,6 +280,25 @@ function notPublished(name, origin, url, cause) {
261
280
  `refusal until ${remedy(cause, origin)}.`,
262
281
  ];
263
282
  }
283
+ /** Why the origin could not be claimed for this identity; nothing was deployed in any case. */
284
+ function notClaimed(origin, cause) {
285
+ switch (cause.code) {
286
+ case 'REGISTRY_ORIGIN_CLAIMED':
287
+ return [
288
+ `${origin} is already claimed in the Domain registry, and you may not read it: nothing was deployed.`,
289
+ 'An administrator of the Domain grants you domain_admin to publish it.',
290
+ ];
291
+ case 'REGISTRY_ORIGIN_RESERVED':
292
+ return [
293
+ `${origin} is under astrale.ai, which Astrale operators register: nothing was deployed.`,
294
+ ];
295
+ default:
296
+ return [
297
+ `${origin} is not in the Domain registry and could not be claimed: ${cause.code}: ${cause.message}`,
298
+ 'Nothing was deployed or published. Rerun publish: a claim is safe to repeat.',
299
+ ];
300
+ }
301
+ }
264
302
  /** CT29: a change may have applied, or the answer could not be read. */
265
303
  function unconfirmed(error) {
266
304
  const reason = error.details?.reason;
@@ -70,6 +70,13 @@ export interface RegistryYank {
70
70
  export interface DomainRegistry {
71
71
  /** The Domain's index, or `undefined` when it is absent or not readable by the caller. */
72
72
  index(origin: string): Promise<RegistryIndex | undefined>;
73
+ /**
74
+ * Claim one origin: Admin gives an origin no one has to its first claimer, who administers its
75
+ * Domain. Idempotent for a caller who administers the Domain, so a rerun is safe. An origin
76
+ * another account holds is refused (`REGISTRY_ORIGIN_CLAIMED`), as is one under `astrale.ai`
77
+ * for anyone but an Astrale operator (`REGISTRY_ORIGIN_RESERVED`).
78
+ */
79
+ claim(origin: string): Promise<void>;
73
80
  /** The bundle bytes of one Publication of the index, digest and Schema identity verified. */
74
81
  bundle(origin: string, publication: RegistryPublication): Promise<Uint8Array>;
75
82
  /**
@@ -80,6 +80,14 @@ export async function openDomainRegistry(input, dependencies = {
80
80
  throw cause;
81
81
  }
82
82
  },
83
+ async claim(origin) {
84
+ const document = await command({ executable, ...machine(['__domain-registry', 'claim', origin]) }, { stdout: DOCUMENT_LIMIT, timeoutMs: CHANGE_TIMEOUT_MS, change: true });
85
+ if (document.format !== 'astrale.registry-claim-result' ||
86
+ document.version !== 1 ||
87
+ document.origin !== origin) {
88
+ throw protocolError(`Astrale CLI answered no claim result of ${origin}.`);
89
+ }
90
+ },
83
91
  async bundle(origin, publication) {
84
92
  const directory = await mkdtemp(join(tmpdir(), 'astrale-registry-'));
85
93
  try {
@@ -12,6 +12,12 @@ export declare const MINIMUM_REGISTRY_CLI_VERSION = "1.0.0-beta.128";
12
12
  * 1.0.0-beta.128 and older were released without it.
13
13
  */
14
14
  export declare const MINIMUM_INSTALLATIONS_CLI_VERSION = "1.0.0-beta.129";
15
+ /**
16
+ * The first Astrale CLI release that claims an origin (`astrale __domain-registry claim`), which
17
+ * `astrale-domain publish` does before the first version of a Domain no one has registered.
18
+ * 1.0.0-beta.136 and older were released without it.
19
+ */
20
+ export declare const MINIMUM_CLAIM_CLI_VERSION = "1.0.0-beta.137";
15
21
  export interface RegistryExecutableDependencies {
16
22
  readonly candidates: () => Promise<readonly string[]>;
17
23
  readonly run: (input: RegistryProcessInput) => Promise<RegistryProcessResult>;
@@ -17,6 +17,12 @@ export const MINIMUM_REGISTRY_CLI_VERSION = '1.0.0-beta.128';
17
17
  * 1.0.0-beta.128 and older were released without it.
18
18
  */
19
19
  export const MINIMUM_INSTALLATIONS_CLI_VERSION = '1.0.0-beta.129';
20
+ /**
21
+ * The first Astrale CLI release that claims an origin (`astrale __domain-registry claim`), which
22
+ * `astrale-domain publish` does before the first version of a Domain no one has registered.
23
+ * 1.0.0-beta.136 and older were released without it.
24
+ */
25
+ export const MINIMUM_CLAIM_CLI_VERSION = '1.0.0-beta.137';
20
26
  /**
21
27
  * Resolve one Astrale CLI for a whole command, the official installation before PATH, and admit
22
28
  * it only when it serves the registry plumbing, so an older CLI is refused by name instead of
@@ -3,7 +3,7 @@
3
3
  * registry plumbing (CT29), with the caller's own credential and the CLI's configured Admin target.
4
4
  */
5
5
  export { RegistryCliError, openDomainRegistry, type DomainRegistry, type DomainRegistryDependencies, type RegistryBundle, type RegistryDigest, type RegistryIndex, type RegistryPublication, type RegistryPublishRequest, type RegistryPublishResult, type RegistryYank, } from './client.js';
6
- export { MINIMUM_INSTALLATIONS_CLI_VERSION, MINIMUM_REGISTRY_CLI_VERSION, resolveRegistryExecutable, } from './executable.js';
6
+ export { MINIMUM_CLAIM_CLI_VERSION, MINIMUM_INSTALLATIONS_CLI_VERSION, MINIMUM_REGISTRY_CLI_VERSION, resolveRegistryExecutable, } from './executable.js';
7
7
  export { isAdminFailure } from './installations.js';
8
8
  export type { InstallationUnknownReason, InstanceInstallation, InstanceListing, } from './installations.js';
9
9
  export { RegistryProcessTimeoutError } from './process.js';
@@ -3,6 +3,6 @@
3
3
  * registry plumbing (CT29), with the caller's own credential and the CLI's configured Admin target.
4
4
  */
5
5
  export { RegistryCliError, openDomainRegistry, } from './client.js';
6
- export { MINIMUM_INSTALLATIONS_CLI_VERSION, MINIMUM_REGISTRY_CLI_VERSION, resolveRegistryExecutable, } from './executable.js';
6
+ export { MINIMUM_CLAIM_CLI_VERSION, MINIMUM_INSTALLATIONS_CLI_VERSION, MINIMUM_REGISTRY_CLI_VERSION, resolveRegistryExecutable, } from './executable.js';
7
7
  export { isAdminFailure } from './installations.js';
8
8
  export { RegistryProcessTimeoutError } from './process.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/sdk",
3
- "version": "0.6.0-beta.25",
3
+ "version": "0.6.0-beta.27",
4
4
  "description": "Schema-first SDK for defining, composing, and deploying Astrale domains",
5
5
  "keywords": [
6
6
  "astrale",