@hivemagnus/magnus-contracts 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/release.d.ts CHANGED
@@ -48,11 +48,11 @@ export declare const migrationImpactSchema: z.ZodEnum<{
48
48
  }>;
49
49
  export declare const releaseMigrationSchema: z.ZodObject<{
50
50
  name: z.ZodString;
51
- impact: z.ZodEnum<{
51
+ impact: z.ZodCatch<z.ZodEnum<{
52
52
  fast: "fast";
53
53
  slow: "slow";
54
54
  "one-way": "one-way";
55
- }>;
55
+ }>>;
56
56
  note: z.ZodDefault<z.ZodString>;
57
57
  }, z.core.$strip>;
58
58
  export declare const releaseManifestSchema: z.ZodObject<{
@@ -95,11 +95,11 @@ export declare const releaseManifestSchema: z.ZodObject<{
95
95
  }, z.core.$strip>>>;
96
96
  migrations: z.ZodDefault<z.ZodArray<z.ZodObject<{
97
97
  name: z.ZodString;
98
- impact: z.ZodEnum<{
98
+ impact: z.ZodCatch<z.ZodEnum<{
99
99
  fast: "fast";
100
100
  slow: "slow";
101
101
  "one-way": "one-way";
102
- }>;
102
+ }>>;
103
103
  note: z.ZodDefault<z.ZodString>;
104
104
  }, z.core.$strip>>>;
105
105
  agent: z.ZodObject<{
@@ -108,6 +108,7 @@ export declare const releaseManifestSchema: z.ZodObject<{
108
108
  }, z.core.$strip>;
109
109
  summary: z.ZodDefault<z.ZodString>;
110
110
  notesUrl: z.ZodOptional<z.ZodString>;
111
+ allowScripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
111
112
  }, z.core.$strip>;
112
113
  export type ReleaseManifest = z.infer<typeof releaseManifestSchema>;
113
114
  export type ReleaseEnvChange = z.infer<typeof releaseEnvChangeSchema>;
@@ -136,7 +137,17 @@ export interface UpgradePath {
136
137
  * `minUpgradeFrom` is newer than `from` blocks the path.
137
138
  */
138
139
  export declare function summarizeUpgradePath(manifests: Iterable<ReleaseManifest>, from: string, to: string): UpgradePath;
140
+ export interface PackumentReleases {
141
+ manifests: ReleaseManifest[];
142
+ /** Versions that carry a `magnusRelease` this code cannot parse (a newer schema). */
143
+ unparsable: string[];
144
+ /** Versions npm marks deprecated. */
145
+ deprecated: string[];
146
+ /** `dist-tags.latest`, when present. */
147
+ latest: string | null;
148
+ }
139
149
  /** Reads the manifests embedded as `magnusRelease` in a full npm packument. */
150
+ export declare function readPackument(packument: unknown): PackumentReleases;
140
151
  export declare function manifestsFromPackument(packument: unknown): ReleaseManifest[];
141
152
  export declare const AGENT_SELF_UPGRADE_PROTOCOL = 1;
142
153
  export declare const agentUpgradeStateSchema: z.ZodEnum<{
@@ -148,14 +159,14 @@ export declare const agentUpgradeStateSchema: z.ZodEnum<{
148
159
  reverted: "reverted";
149
160
  }>;
150
161
  export declare const agentUpgradeReportSchema: z.ZodObject<{
151
- state: z.ZodEnum<{
162
+ state: z.ZodUnion<readonly [z.ZodEnum<{
152
163
  failed: "failed";
153
164
  idle: "idle";
154
165
  staged: "staged";
155
166
  trial: "trial";
156
167
  confirmed: "confirmed";
157
168
  reverted: "reverted";
158
- }>;
169
+ }>, z.ZodString]>;
159
170
  from: z.ZodOptional<z.ZodNullable<z.ZodString>>;
160
171
  to: z.ZodOptional<z.ZodNullable<z.ZodString>>;
161
172
  requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -163,6 +174,11 @@ export declare const agentUpgradeReportSchema: z.ZodObject<{
163
174
  attempt: z.ZodOptional<z.ZodNumber>;
164
175
  updatedAt: z.ZodOptional<z.ZodString>;
165
176
  }, z.core.$strip>;
177
+ /** The agent's local sticky managed-enrollment marker, as it reports it. */
178
+ export declare const agentManagedEnrollmentSchema: z.ZodObject<{
179
+ nodeId: z.ZodString;
180
+ nodeFqdn: z.ZodString;
181
+ }, z.core.$strip>;
166
182
  export declare const agentSelfUpgradeStatusSchema: z.ZodObject<{
167
183
  protocol: z.ZodNumber;
168
184
  launcherProtocol: z.ZodNullable<z.ZodNumber>;
@@ -174,14 +190,14 @@ export declare const agentSelfUpgradeStatusSchema: z.ZodObject<{
174
190
  enabled: z.ZodBoolean;
175
191
  reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
176
192
  upgrade: z.ZodOptional<z.ZodNullable<z.ZodObject<{
177
- state: z.ZodEnum<{
193
+ state: z.ZodUnion<readonly [z.ZodEnum<{
178
194
  failed: "failed";
179
195
  idle: "idle";
180
196
  staged: "staged";
181
197
  trial: "trial";
182
198
  confirmed: "confirmed";
183
199
  reverted: "reverted";
184
- }>;
200
+ }>, z.ZodString]>;
185
201
  from: z.ZodOptional<z.ZodNullable<z.ZodString>>;
186
202
  to: z.ZodOptional<z.ZodNullable<z.ZodString>>;
187
203
  requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -189,6 +205,11 @@ export declare const agentSelfUpgradeStatusSchema: z.ZodObject<{
189
205
  attempt: z.ZodOptional<z.ZodNumber>;
190
206
  updatedAt: z.ZodOptional<z.ZodString>;
191
207
  }, z.core.$strip>>>;
208
+ confirmSeconds: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
209
+ managedEnrollment: z.ZodOptional<z.ZodNullable<z.ZodObject<{
210
+ nodeId: z.ZodString;
211
+ nodeFqdn: z.ZodString;
212
+ }, z.core.$strip>>>;
192
213
  }, z.core.$strip>;
193
214
  export declare const agentUpgradeRequestSchema: z.ZodObject<{
194
215
  version: z.ZodString;
@@ -199,4 +220,13 @@ export declare const agentUpgradeRequestSchema: z.ZodObject<{
199
220
  export type AgentUpgradeState = z.infer<typeof agentUpgradeStateSchema>;
200
221
  export type AgentUpgradeReport = z.infer<typeof agentUpgradeReportSchema>;
201
222
  export type AgentSelfUpgradeStatus = z.infer<typeof agentSelfUpgradeStatusSchema>;
223
+ export type AgentManagedEnrollment = z.infer<typeof agentManagedEnrollmentSchema>;
202
224
  export type AgentUpgradeRequest = z.infer<typeof agentUpgradeRequestSchema>;
225
+ /** Name for the schema kept aside during a restore. */
226
+ export declare function restoreAsideSchema(now: Date): string;
227
+ /** Moves `public` aside and recreates it with the same owner and privileges. */
228
+ export declare function restoreSwapSql(aside: string): string;
229
+ /** After a failed restore: drop the partial schema and put the original back. */
230
+ export declare function restoreRevertSql(aside: string): string;
231
+ /** After a successful restore: drop the schema kept aside. */
232
+ export declare function restoreFinishSql(aside: string): string;
package/dist/release.js CHANGED
@@ -136,7 +136,8 @@ export const releaseEnvChangeSchema = z.object({
136
136
  export const migrationImpactSchema = z.enum(['fast', 'slow', 'one-way']);
137
137
  export const releaseMigrationSchema = z.object({
138
138
  name: z.string().min(1),
139
- impact: migrationImpactSchema,
139
+ // An impact a newer release introduces is treated as the most cautious one.
140
+ impact: migrationImpactSchema.catch('one-way'),
140
141
  note: z.string().default(''),
141
142
  });
142
143
  export const releaseManifestSchema = z.object({
@@ -155,6 +156,8 @@ export const releaseManifestSchema = z.object({
155
156
  agent: z.object({ selfUpgradeProtocol: z.number().int().nonnegative(), minLauncher: z.number().int().nonnegative() }),
156
157
  summary: z.string().default(''),
157
158
  notesUrl: z.string().url().optional(),
159
+ /** npm install scripts the release's dependency tree needs (`allowScripts` of the version install). */
160
+ allowScripts: z.record(z.string(), z.boolean()).optional(),
158
161
  });
159
162
  /**
160
163
  * Merges the manifests of every release in (from, to]. Env names added and
@@ -200,35 +203,57 @@ export function summarizeUpgradePath(manifests, from, to) {
200
203
  };
201
204
  }
202
205
  /** Reads the manifests embedded as `magnusRelease` in a full npm packument. */
203
- export function manifestsFromPackument(packument) {
204
- const versions = packument?.versions ?? {};
205
- const manifests = [];
206
- for (const entry of Object.values(versions)) {
207
- const parsed = releaseManifestSchema.safeParse(entry?.magnusRelease);
206
+ export function readPackument(packument) {
207
+ const doc = packument;
208
+ const result = { manifests: [], unparsable: [], deprecated: [], latest: null };
209
+ for (const [version, entry] of Object.entries(doc?.versions ?? {})) {
210
+ if (typeof entry?.deprecated === 'string' && entry.deprecated)
211
+ result.deprecated.push(version);
212
+ if (entry?.magnusRelease === undefined)
213
+ continue;
214
+ const parsed = releaseManifestSchema.safeParse(entry.magnusRelease);
208
215
  if (parsed.success)
209
- manifests.push(parsed.data);
216
+ result.manifests.push(parsed.data);
217
+ else
218
+ result.unparsable.push(version);
210
219
  }
211
- return manifests;
220
+ const latest = doc?.['dist-tags']?.['latest'];
221
+ if (typeof latest === 'string' && isVersion(latest))
222
+ result.latest = latest;
223
+ return result;
224
+ }
225
+ export function manifestsFromPackument(packument) {
226
+ return readPackument(packument).manifests;
212
227
  }
213
228
  // Agent self-upgrade wire contract.
214
229
  export const AGENT_SELF_UPGRADE_PROTOCOL = 1;
215
230
  export const agentUpgradeStateSchema = z.enum(['idle', 'staged', 'trial', 'confirmed', 'reverted', 'failed']);
231
+ /** Known states plus any future one, so a newer agent's report is never dropped whole. */
232
+ const reportedUpgradeState = z.union([agentUpgradeStateSchema, z.string().regex(/^[a-z][a-z0-9_-]{0,31}$/)]);
216
233
  export const agentUpgradeReportSchema = z.object({
217
- state: agentUpgradeStateSchema,
234
+ state: reportedUpgradeState,
218
235
  from: z.string().nullable().optional(),
219
236
  to: z.string().nullable().optional(),
220
237
  requestId: z.string().max(128).nullable().optional(),
221
- reason: z.string().max(500).nullable().optional(),
238
+ reason: z.string().max(1000).nullable().optional(),
222
239
  attempt: z.number().int().nonnegative().optional(),
223
240
  updatedAt: z.string().optional(),
224
241
  });
242
+ /** The agent's local sticky managed-enrollment marker, as it reports it. */
243
+ export const agentManagedEnrollmentSchema = z.object({
244
+ nodeId: z.string().min(1).max(128),
245
+ nodeFqdn: z.string().min(1).max(253),
246
+ });
225
247
  export const agentSelfUpgradeStatusSchema = z.object({
226
248
  protocol: z.number().int().nonnegative(),
227
249
  launcherProtocol: z.number().int().nonnegative().nullable(),
228
250
  layout: z.enum(['versioned', 'legacy', 'container']),
229
251
  enabled: z.boolean(),
230
- reason: z.string().max(300).nullable().optional(),
252
+ reason: z.string().max(1000).nullable().optional(),
231
253
  upgrade: agentUpgradeReportSchema.nullable().optional(),
254
+ /** Seconds a new version has on trial before the launcher switches back (MAGNUS_AGENT_UPGRADE_CONFIRM_SECONDS). */
255
+ confirmSeconds: z.number().int().positive().max(86_400).nullable().optional(),
256
+ managedEnrollment: agentManagedEnrollmentSchema.nullable().optional(),
232
257
  });
233
258
  export const agentUpgradeRequestSchema = z.object({
234
259
  version: versionString,
@@ -236,3 +261,34 @@ export const agentUpgradeRequestSchema = z.object({
236
261
  requestId: z.string().min(1).max(128),
237
262
  packageName: z.string().default('@hivemagnus/magnus-agent'),
238
263
  });
264
+ // Database restore. A dump is restored into an empty `public` schema so that
265
+ // tables a newer release created do not survive next to the restored ones:
266
+ // the live schema is renamed aside, a new one with the same owner and grants
267
+ // takes its place, `pg_restore --single-transaction` fills it, and the old
268
+ // schema is dropped only after the restore committed (or renamed back if it
269
+ // failed). Each step is one transaction.
270
+ /** Name for the schema kept aside during a restore. */
271
+ export function restoreAsideSchema(now) {
272
+ return `magnus_pre_restore_${now.toISOString().replace(/\D/g, '').slice(0, 14)}`;
273
+ }
274
+ /** Moves `public` aside and recreates it with the same owner and privileges. */
275
+ export function restoreSwapSql(aside) {
276
+ return `DO $magnus$ DECLARE owner_name text; grant_row record; BEGIN
277
+ SELECT pg_get_userbyid(nspowner) INTO owner_name FROM pg_namespace WHERE nspname = 'public';
278
+ IF owner_name IS NULL THEN RAISE EXCEPTION 'schema public does not exist'; END IF;
279
+ EXECUTE format('ALTER SCHEMA public RENAME TO %I', '${aside}');
280
+ EXECUTE format('CREATE SCHEMA public AUTHORIZATION %I', owner_name);
281
+ FOR grant_row IN SELECT CASE WHEN a.grantee = 0 THEN 'PUBLIC' ELSE quote_ident(pg_get_userbyid(a.grantee)) END AS grantee, a.privilege_type
282
+ FROM pg_namespace n, aclexplode(n.nspacl) a WHERE n.nspname = '${aside}' LOOP
283
+ EXECUTE format('GRANT %s ON SCHEMA public TO %s', grant_row.privilege_type, grant_row.grantee);
284
+ END LOOP;
285
+ END $magnus$;`;
286
+ }
287
+ /** After a failed restore: drop the partial schema and put the original back. */
288
+ export function restoreRevertSql(aside) {
289
+ return `BEGIN; DROP SCHEMA public CASCADE; ALTER SCHEMA "${aside}" RENAME TO public; COMMIT;`;
290
+ }
291
+ /** After a successful restore: drop the schema kept aside. */
292
+ export function restoreFinishSql(aside) {
293
+ return `DROP SCHEMA "${aside}" CASCADE;`;
294
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemagnus/magnus-contracts",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Shared Zod schemas and TypeScript types for the Magnus server, UI and node agent wire contracts.",
5
5
  "keywords": [
6
6
  "magnus",