@crvouga/dev-fleet 0.4.0 → 0.6.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 (63) hide show
  1. package/README.md +3 -1
  2. package/ansible/macos/policy.json +1 -0
  3. package/ansible/platforms.json +111 -0
  4. package/ansible/ubuntu/authorize-sudo.sh +7 -16
  5. package/ansible/ubuntu/baseline.yml +6 -28
  6. package/ansible/ubuntu/disk-gc.py +186 -4
  7. package/ansible/ubuntu/policy.json +18 -3
  8. package/ansible/ubuntu/t3-desktop.yml +2 -2
  9. package/ansible/ubuntu/tailscale.yml +20 -9
  10. package/ansible/ubuntu/tasks/dpkg.yml +46 -0
  11. package/ansible/ubuntu/tasks/github.yml +50 -0
  12. package/ansible/ubuntu/tasks/install.yml +38 -0
  13. package/ansible/ubuntu/tasks/packages.yml +4 -55
  14. package/ansible/ubuntu/tasks/release.yml +25 -0
  15. package/ansible/ubuntu/tasks/resources.yml +6 -5
  16. package/ansible/ubuntu/tasks/snapshot.yml +50 -0
  17. package/ansible/ubuntu/tasks/unattended-upgrades.yml +24 -0
  18. package/bootstrap/fleet-remote-bootstrap.sh +18 -41
  19. package/bootstrap/worker-auth.ts +6 -7
  20. package/bootstrap/worker-github.ts +55 -44
  21. package/docs/authentication.md +4 -1
  22. package/docs/consumer-setup.md +37 -30
  23. package/docs/declared.md +4 -5
  24. package/docs/github.md +107 -0
  25. package/docs/operations.md +1 -1
  26. package/docs/runbooks.md +17 -6
  27. package/docs/support-matrix.md +36 -0
  28. package/docs/ubuntu-sync.md +14 -12
  29. package/docs/worker-contract.md +28 -1
  30. package/package.json +2 -2
  31. package/schema/check-ids.json +55 -7
  32. package/schema/fleet.schema.json +86 -4
  33. package/src/auth-checks.ts +14 -6
  34. package/src/cli/fleet-sync-manager.ts +9 -0
  35. package/src/cli/fleet-sync-remote.ts +1 -1
  36. package/src/cli/github-verify.ts +57 -0
  37. package/src/cli/register-fleet.ts +2 -0
  38. package/src/cli/registry.ts +7 -0
  39. package/src/definition.ts +29 -8
  40. package/src/github/checks.ts +412 -0
  41. package/src/github/converge.ts +62 -0
  42. package/src/github/copilot.ts +54 -0
  43. package/src/github/credential.ts +21 -0
  44. package/src/github/policy.ts +141 -0
  45. package/src/github/sync.ts +123 -0
  46. package/src/github/workflow.ts +223 -0
  47. package/src/machine/platform.ts +48 -28
  48. package/src/machine/support-matrix.ts +76 -0
  49. package/src/manager-sync.ts +15 -7
  50. package/src/network-definition.ts +1 -1
  51. package/src/node-converge-linux.ts +3 -2
  52. package/src/node-converge-shared.ts +6 -2
  53. package/src/node-converge.ts +1 -1
  54. package/src/platform/debian-version.ts +62 -0
  55. package/src/platform/ubuntu-audit.ts +11 -4
  56. package/src/platform/ubuntu-release.ts +41 -0
  57. package/src/remote-bootstrap.ts +2 -0
  58. package/src/repair-catalog.ts +2 -2
  59. package/src/secrets.ts +58 -13
  60. package/src/service-auth.ts +2 -2
  61. package/src/worker-access-checks.ts +66 -16
  62. package/src/worker-host-checks.ts +36 -10
  63. package/src/worker-readiness.ts +1 -1
@@ -5,6 +5,8 @@ import { verifyResourceSafety } from './platform/resource-verify';
5
5
  import policy from '../ansible/ubuntu/policy.json';
6
6
  import { userInfo } from 'node:os';
7
7
  import { T3_HEALTH_SCRIPT, runningVersionCheck } from './platform/t3-service';
8
+ import { compareDebianVersions } from './platform/debian-version';
9
+ import { packagePins, ubuntuRelease } from './platform/ubuntu-release';
8
10
  import type { Check, Runner } from './types';
9
11
 
10
12
  function check(id: string, ok: boolean, summary: string): Check {
@@ -22,6 +24,34 @@ function check(id: string, ok: boolean, summary: string): Check {
22
24
  : {}),
23
25
  };
24
26
  }
27
+ /** A pin is a minimum (docs/worker-contract.md): Ubuntu's security updates
28
+ * may move a package past it, which is reported but never undone. */
29
+ export function pinnedPackage(
30
+ name: string,
31
+ pinned: string,
32
+ installed: string | undefined
33
+ ): Check {
34
+ const order =
35
+ installed === undefined ? -1 : compareDebianVersions(installed, pinned);
36
+ if (order <= 0)
37
+ return check(
38
+ `package:${name}`,
39
+ order === 0,
40
+ order === 0
41
+ ? 'Installed at the version the policy pins.'
42
+ : `PACKAGE_BELOW_PIN ${name} ${installed ?? 'missing'}, pinned ${pinned}`
43
+ );
44
+ return {
45
+ id: `worker:package:${name}`,
46
+ status: 'warn',
47
+ summary: `PACKAGE_NEWER_THAN_PIN ${name} ${installed}, pinned ${pinned}`,
48
+ remedy: {
49
+ action:
50
+ 'An unattended security update moved this package past its pin, and it is kept. Raise the pin in the Ubuntu policy when the snapshot moves.',
51
+ },
52
+ };
53
+ }
54
+
25
55
  /** Observed unit state for a failed service check, e.g.
26
56
  * `SERVICE_NOT_INSTALLED beszel-agent.service (inactive)`. */
27
57
  export function serviceState(name: string, show: string): string {
@@ -56,17 +86,13 @@ export async function workerHostChecks(
56
86
  audit.passwordlessSudo,
57
87
  'Designated worker user has noninteractive sudo.'
58
88
  ),
59
- ...Object.entries(policy.packages).map(([name, version]) =>
60
- check(
61
- `package:${name}`,
62
- audit.packages[name] === version,
63
- 'Exact declarative Ubuntu package version.'
64
- )
89
+ ...Object.entries(packagePins(ubuntuRelease(audit.release))).map(
90
+ ([name, version]) => pinnedPackage(name, version, audit.packages[name])
65
91
  ),
66
- check(
67
- 'package:tailscale',
68
- audit.packages['tailscale'] === policy.tailscale.version,
69
- 'Exact declarative Tailscale version.'
92
+ pinnedPackage(
93
+ 'tailscale',
94
+ policy.tailscale.version,
95
+ audit.packages['tailscale']
70
96
  ),
71
97
  ];
72
98
  for (const name of policy.alwaysOnServices) {
@@ -16,7 +16,7 @@ export async function workerReadiness(
16
16
  root = process.cwd()
17
17
  ): Promise<Check[]> {
18
18
  const host = await workerHostChecks(userInfo().username, run);
19
- const access = await workerAccessChecks(run);
19
+ const access = await workerAccessChecks(run, nodeId);
20
20
  const revision = await run(['git', 'rev-parse', 'HEAD']);
21
21
  const singleton = await run(
22
22
  [