@celilo/cli 0.17.0 → 0.19.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/CELILO_CORE_MODULES.md +1 -1
  2. package/CELILO_SUBSYSTEMS.md +38 -9
  3. package/drizzle/0019_backup_pid.sql +18 -0
  4. package/drizzle/meta/_journal.json +7 -0
  5. package/package.json +5 -5
  6. package/schemas/system_config.json +1 -1
  7. package/src/api/remote-client.test.ts +62 -0
  8. package/src/api/serve.ts +14 -6
  9. package/src/cli/command-tree-parser.ts +0 -1
  10. package/src/cli/commands/apt-upgrade.test.ts +20 -1
  11. package/src/cli/commands/apt-upgrade.ts +12 -2
  12. package/src/cli/commands/backup-sweep.ts +62 -0
  13. package/src/cli/commands/events.ts +90 -0
  14. package/src/cli/commands/module-operations.test.ts +45 -1
  15. package/src/cli/commands/module-operations.ts +35 -12
  16. package/src/cli/commands/module-show.ts +1 -0
  17. package/src/cli/commands/module-update.test.ts +72 -1
  18. package/src/cli/commands/module-update.ts +45 -22
  19. package/src/cli/commands/system-audit.ts +2 -0
  20. package/src/cli/commands/system-migrate.test.ts +56 -0
  21. package/src/cli/commands/system-migrate.ts +92 -4
  22. package/src/cli/commands/system-update.ts +5 -0
  23. package/src/cli/completion.ts +19 -0
  24. package/src/cli/fuel-gauge.ts +0 -1
  25. package/src/cli/generate-zsh-completion.ts +1 -1
  26. package/src/cli/index.ts +5 -1
  27. package/src/cli/tui/audit-state.ts +4 -0
  28. package/src/cli/tui/audit-tui.test.tsx +0 -1
  29. package/src/db/migration-status.test.ts +114 -0
  30. package/src/db/migration-status.ts +78 -0
  31. package/src/db/schema-introspection.ts +8 -1
  32. package/src/db/schema.ts +53 -9
  33. package/src/hooks/capability-loader.ts +30 -1
  34. package/src/ipam/allocator.ts +13 -3
  35. package/src/services/alerting/builtin-monitors.test.ts +42 -0
  36. package/src/services/alerting/builtin-monitors.ts +2 -0
  37. package/src/services/alerting/builtin-source.ts +15 -0
  38. package/src/services/audit/abandoned-operations.test.ts +73 -0
  39. package/src/services/audit/abandoned-operations.ts +0 -0
  40. package/src/services/audit/disk-space.test.ts +111 -0
  41. package/src/services/audit/disk-space.ts +114 -0
  42. package/src/services/audit/index.test.ts +1 -0
  43. package/src/services/audit/index.ts +9 -0
  44. package/src/services/audit/types.ts +2 -0
  45. package/src/services/backup-create.ts +4 -4
  46. package/src/services/backup-in-flight-refusal.test.ts +2 -0
  47. package/src/services/backup-metadata.ts +4 -0
  48. package/src/services/backup-staging.test.ts +134 -0
  49. package/src/services/backup-staging.ts +192 -0
  50. package/src/services/backup-sweep.test.ts +68 -0
  51. package/src/services/backup-sweep.ts +62 -0
  52. package/src/services/bus-interview.ts +11 -5
  53. package/src/services/config-interview.ts +1 -1
  54. package/src/services/deploy-ansible.ts +0 -1
  55. package/src/services/disk-probe.test.ts +74 -0
  56. package/src/services/disk-probe.ts +145 -0
  57. package/src/services/events-daemon.test.ts +244 -0
  58. package/src/services/events-daemon.ts +295 -8
  59. package/src/services/fleet-checks.test.ts +75 -4
  60. package/src/services/fleet-checks.ts +97 -12
  61. package/src/services/interview-errors.ts +20 -0
  62. package/src/services/module-operations.test.ts +22 -0
  63. package/src/services/module-operations.ts +48 -1
  64. package/src/services/module-subscriptions.test.ts +39 -6
  65. package/src/services/module-subscriptions.ts +6 -4
  66. package/src/services/module-types-generator.test.ts +6 -3
  67. package/src/services/module-types-generator.ts +12 -7
  68. package/src/services/remote-responder.test.ts +70 -0
  69. package/src/services/remote-responder.ts +27 -10
  70. package/src/services/responder-probe.ts +3 -1
  71. package/src/services/update/orchestrator.test.ts +1 -0
  72. package/src/variables/context.ts +6 -1
@@ -20,6 +20,9 @@ const NO_SCHEMAS = defineEvents({});
20
20
  /** The normalized question handed to the wire (mirrors InterviewMessage). */
21
21
  export interface WireInterview {
22
22
  id: string;
23
+ /** The question's stable identity, so a client can pre-stage `<scope>.<key>`. */
24
+ scope: string;
25
+ key: string;
23
26
  kind: InterviewRequiredPayload['kind'];
24
27
  message: string;
25
28
  description?: string;
@@ -54,16 +57,30 @@ export function startRemoteResponder(opts: RemoteResponderOptions): RemoteRespon
54
57
  return;
55
58
  }
56
59
 
57
- const value = await opts.ask({
58
- id: String(event.id),
59
- kind: payload.kind,
60
- message: payload.message,
61
- description: payload.description,
62
- defaultValue: payload.defaultValue,
63
- placeholder: payload.placeholder,
64
- options: payload.options,
65
- required: payload.required,
66
- });
60
+ let value: unknown;
61
+ try {
62
+ value = await opts.ask({
63
+ id: String(event.id),
64
+ scope: payload.scope,
65
+ key: payload.key,
66
+ kind: payload.kind,
67
+ message: payload.message,
68
+ description: payload.description,
69
+ defaultValue: payload.defaultValue,
70
+ placeholder: payload.placeholder,
71
+ options: payload.options,
72
+ required: payload.required,
73
+ });
74
+ } catch (err) {
75
+ // The client had no way to answer. Reply with the reason so the waiting
76
+ // command fails loudly — never let the question decay to its default.
77
+ bus.emitRaw(
78
+ `${event.type}.reply`,
79
+ { error: err instanceof Error ? err.message : String(err) },
80
+ { replyFor: event.id, emittedBy: me },
81
+ );
82
+ return;
83
+ }
67
84
 
68
85
  bus.emitRaw(`${event.type}.reply`, { value }, { replyFor: event.id, emittedBy: me });
69
86
  });
@@ -14,6 +14,7 @@
14
14
 
15
15
  import { defineEvents, openBus } from '@celilo/event-bus';
16
16
  import { getEventBusPath } from '../config/paths';
17
+ import { InterviewUnansweredError } from './interview-errors';
17
18
 
18
19
  const NO_SCHEMAS = defineEvents({});
19
20
 
@@ -63,7 +64,8 @@ export async function ensureResponderForInterview(queryType: string): Promise<vo
63
64
  if (process.stdin.isTTY) return;
64
65
  const available = await probeForResponder(getEventBusPath());
65
66
  if (available) return;
66
- throw new Error(
67
+ throw new InterviewUnansweredError(
68
+ queryType,
67
69
  `No responder is listening and stdin isn't a TTY, so this interview prompt can't be answered (${queryType}).
68
70
 
69
71
  Either:
@@ -76,6 +76,7 @@ const cleanAudit: AuditDeps = {
76
76
  moduleConfigs: { modules: [] },
77
77
  health: { results: [] },
78
78
  backups: { modules: [] },
79
+ abandonedOperations: { records: [] },
79
80
  undeployedModules: { modules: [] },
80
81
  unconfiguredModules: { modules: [] },
81
82
  servicesCredentials: { results: [] },
@@ -5,6 +5,7 @@ import type { DbClient } from '../db/client';
5
5
  import {
6
6
  capabilities,
7
7
  containerServices,
8
+ isAllocatableZone,
8
9
  machines,
9
10
  moduleConfigs,
10
11
  moduleInfrastructure,
@@ -391,7 +392,11 @@ export async function buildResolutionContext(
391
392
  .get();
392
393
  isProxmox = svc?.providerName === 'proxmox';
393
394
  }
394
- if (isProxmox && zone !== 'external') {
395
+ // `isAllocatableZone`, not `zone !== 'external'`: that check was written
396
+ // when `external` was the only zone celilo does not address, and it
397
+ // silently became wrong the moment `vpn` joined it — a VPN client subnet
398
+ // is assigned by the tunnel module, so allocating into it would collide.
399
+ if (isProxmox && isAllocatableZone(zone)) {
395
400
  await db.transaction(async (tx) => {
396
401
  const existing = await getAllocation(moduleId, tx);
397
402
  const allocation = existing ?? (await allocateResources(moduleId, zone, tx));