@kici-dev/orchestrator 0.14.2 → 0.16.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 (176) hide show
  1. package/dist/__test-helpers__/peer-mutual-auth.d.ts +42 -0
  2. package/dist/__test-helpers__/scratch-db.d.ts +16 -0
  3. package/dist/agent/host-roster.d.ts +100 -37
  4. package/dist/agent/registry.d.ts +1 -8
  5. package/dist/app-on-error.d.ts +1 -1
  6. package/dist/app.d.ts +4 -2
  7. package/dist/artifacts/artifact-store.d.ts +0 -2
  8. package/dist/audit/access-log.d.ts +1 -1
  9. package/dist/cache/source-cache.d.ts +1 -1
  10. package/dist/cache/user-cache.d.ts +0 -28
  11. package/dist/cli/api-client.d.ts +27 -1
  12. package/dist/cli/commands/access-log.d.ts +1 -1
  13. package/dist/cli/commands/cold-store-impl.d.ts +7 -84
  14. package/dist/cli/commands/db.d.ts +1 -0
  15. package/dist/cli/commands/host.d.ts +3 -0
  16. package/dist/cli/commands/orchestrator-service/status.d.ts +2 -0
  17. package/dist/cli/commands/org.d.ts +12 -0
  18. package/dist/cli/commands/scaler.d.ts +14 -0
  19. package/dist/cli/commands/secret.d.ts +1 -45
  20. package/dist/cli/commands/service-health.d.ts +21 -13
  21. package/dist/cli/commands/shared/cli-action.d.ts +17 -0
  22. package/dist/cli/commands/shared/db.d.ts +5 -5
  23. package/dist/cli/commands/shared/org-id.d.ts +5 -0
  24. package/dist/cli/commands/shared/service-verbs.d.ts +19 -0
  25. package/dist/cli/commands/shared/table.d.ts +3 -0
  26. package/dist/cli/commands/shared/unbound-context-warning.d.ts +2 -22
  27. package/dist/cli/commands/source-manifest.d.ts +3 -3
  28. package/dist/cli/commands/source.d.ts +23 -0
  29. package/dist/cli/commands/trust-policy.d.ts +7 -31
  30. package/dist/cli/join.d.ts +2 -2
  31. package/dist/cli/kici-admin.d.ts +6 -1
  32. package/dist/cli/local-github-ingress-url.d.ts +6 -0
  33. package/dist/cli/root-option-routing.d.ts +46 -0
  34. package/dist/cli/webhook-url-notes.d.ts +15 -0
  35. package/dist/cli.js +10667 -8461
  36. package/dist/cluster/coordinator-credential.d.ts +21 -0
  37. package/dist/cluster/coordinator.d.ts +2 -2
  38. package/dist/cluster/index.d.ts +4 -4
  39. package/dist/cluster/join-client.d.ts +23 -21
  40. package/dist/cluster/join-handler.d.ts +24 -16
  41. package/dist/cluster/join-protocol-v2.d.ts +84 -0
  42. package/dist/cluster/join-token.d.ts +78 -56
  43. package/dist/cluster/peer-auth-coordinator.d.ts +16 -2
  44. package/dist/cluster/peer-client.d.ts +99 -5
  45. package/dist/cluster/peer-crypto.d.ts +60 -3
  46. package/dist/cluster/peer-discovery.d.ts +67 -0
  47. package/dist/cluster/peer-forget.d.ts +4 -9
  48. package/dist/cluster/peer-handler.d.ts +28 -6
  49. package/dist/cluster/peer-registry.d.ts +15 -1
  50. package/dist/cluster/peer-request-waiters.d.ts +26 -0
  51. package/dist/cluster/scaler-orphans-peer.d.ts +4 -9
  52. package/dist/cluster/scaler-reload-fanout.d.ts +29 -0
  53. package/dist/cluster/scaler-reload-peer.d.ts +16 -0
  54. package/dist/cluster/worker-cluster-settings.d.ts +1 -0
  55. package/dist/cold-store/load-access-log-range.d.ts +3 -3
  56. package/dist/cold-store/tables/access-log.d.ts +4 -12
  57. package/dist/cold-store/tables/event-log.d.ts +8 -19
  58. package/dist/cold-store/tables/execution-jobs.d.ts +7 -24
  59. package/dist/cold-store/tables/execution-runs.d.ts +6 -20
  60. package/dist/cold-store/tables/execution-steps.d.ts +8 -26
  61. package/dist/cold-store/tables/secret-audit-log.d.ts +4 -11
  62. package/dist/config/env-overlay.d.ts +3 -8
  63. package/dist/config/reload.d.ts +9 -2
  64. package/dist/config/schema.d.ts +16 -2
  65. package/dist/config/types.d.ts +6 -2
  66. package/dist/config.d.ts +22 -17
  67. package/dist/contexts/held-runs.d.ts +3 -6
  68. package/dist/dashboard/cursor.d.ts +12 -0
  69. package/dist/dashboard/handler.d.ts +5 -12
  70. package/dist/db/deferred-index-build.d.ts +42 -0
  71. package/dist/db/deferred-indexes.d.ts +3 -37
  72. package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +3 -5
  73. package/dist/db/migrations/157_host_roster_identity_source.d.ts +21 -0
  74. package/dist/db/migrations/158_normalize_legacy_values.d.ts +4 -0
  75. package/dist/db/repos/org-ids-repo.d.ts +87 -0
  76. package/dist/db/schema-snapshot.generated.d.ts +3 -0
  77. package/dist/db/types.d.ts +21 -24
  78. package/dist/fault-injection-types.d.ts +0 -6
  79. package/dist/git/dispatch-git-auth.d.ts +6 -12
  80. package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +25 -13
  81. package/dist/helpers/json.d.ts +3 -0
  82. package/dist/index.d.ts +1 -1
  83. package/dist/index.js +357 -216
  84. package/dist/metrics/prometheus.d.ts +0 -5
  85. package/dist/oidc/id-token-claims.d.ts +1 -1
  86. package/dist/oidc/resolve-signer.d.ts +2 -4
  87. package/dist/orchestrator-core.d.ts +10 -3
  88. package/dist/pipeline/global-eval-round.d.ts +2 -26
  89. package/dist/pipeline/install-secrets-resolver.d.ts +0 -3
  90. package/dist/pipeline/manual-schedule.d.ts +1 -7
  91. package/dist/provenance/dispatch-context.d.ts +5 -7
  92. package/dist/provenance/pending-attestations-repo.d.ts +1 -1
  93. package/dist/provenance/trust-root.d.ts +4 -5
  94. package/dist/provenance/verify-deferred-capture.d.ts +3 -3
  95. package/dist/provider-registry.d.ts +13 -40
  96. package/dist/providers/github/manifest.d.ts +58 -7
  97. package/dist/providers/universal-git/ssh-auth.d.ts +0 -5
  98. package/dist/reporting/check-run-reporter.d.ts +8 -21
  99. package/dist/reporting/check-run-summary.d.ts +2 -2
  100. package/dist/reporting/execution-tracker.d.ts +1 -1
  101. package/dist/reporting/log-chunk-sink.d.ts +1 -1
  102. package/dist/reporting/run-summary-fields.d.ts +25 -0
  103. package/dist/reporting/s3-log-storage.d.ts +2 -2
  104. package/dist/routes/admin-access-log.d.ts +2 -9
  105. package/dist/routes/admin-backends.d.ts +2 -9
  106. package/dist/routes/admin-cluster-name.d.ts +2 -8
  107. package/dist/routes/admin-cluster-settings.d.ts +2 -8
  108. package/dist/routes/admin-config.d.ts +0 -3
  109. package/dist/routes/admin-contexts.d.ts +3 -11
  110. package/dist/routes/admin-db.d.ts +2 -9
  111. package/dist/routes/admin-env.d.ts +33 -0
  112. package/dist/routes/admin-event-dlq.d.ts +2 -9
  113. package/dist/routes/admin-event-inspect.d.ts +2 -9
  114. package/dist/routes/admin-event-log.d.ts +2 -9
  115. package/dist/routes/admin-events.d.ts +3 -13
  116. package/dist/routes/admin-held-runs.d.ts +2 -8
  117. package/dist/routes/admin-list-limit.d.ts +3 -0
  118. package/dist/routes/admin-maintenance.d.ts +2 -9
  119. package/dist/routes/admin-orchestrator-drain.d.ts +2 -9
  120. package/dist/routes/admin-org-settings.d.ts +2 -8
  121. package/dist/routes/admin-orgs.d.ts +27 -0
  122. package/dist/routes/admin-peer-forget.d.ts +2 -9
  123. package/dist/routes/admin-queue-execution.d.ts +3 -10
  124. package/dist/routes/admin-registrations.d.ts +3 -14
  125. package/dist/routes/admin-runs.d.ts +3 -14
  126. package/dist/routes/admin-scaler-orphans.d.ts +2 -9
  127. package/dist/routes/admin-scaler-reload.d.ts +41 -0
  128. package/dist/routes/admin-scheduled-jobs.d.ts +2 -9
  129. package/dist/routes/admin-signing-keys.d.ts +2 -9
  130. package/dist/routes/admin-sources.d.ts +28 -32
  131. package/dist/routes/admin-trust-policy.d.ts +2 -8
  132. package/dist/routes/admin.d.ts +29 -30
  133. package/dist/routes/cluster-join.d.ts +13 -0
  134. package/dist/routes/github-webhook.d.ts +13 -11
  135. package/dist/scaler/bare-metal-backend.d.ts +42 -1
  136. package/dist/scaler/config.d.ts +12 -84
  137. package/dist/scaler/file-reload.d.ts +48 -0
  138. package/dist/scaler/manager.d.ts +47 -33
  139. package/dist/scaler/scaler-state-store.d.ts +5 -0
  140. package/dist/scaler/types.d.ts +8 -9
  141. package/dist/secrets/job-secret-gate.d.ts +2 -5
  142. package/dist/secrets/secret-resolver.d.ts +2 -4
  143. package/dist/security/trust-policy-gate.d.ts +0 -4
  144. package/dist/server.d.ts +6 -17
  145. package/dist/server.js +10933 -10836
  146. package/dist/sources/source-manager.d.ts +0 -24
  147. package/dist/sources/webhook-url-resolvers.d.ts +60 -0
  148. package/dist/standalone.js +10457 -10060
  149. package/dist/worker/reroute-dispatch.d.ts +1 -0
  150. package/dist/worker/reroute-spawn-control.d.ts +1 -3
  151. package/dist/worker-core.d.ts +9 -2
  152. package/dist/ws/agent-handler.d.ts +3 -3
  153. package/dist/ws/dashboard-access.d.ts +57 -0
  154. package/dist/ws/dashboard-backends-handler.d.ts +1 -6
  155. package/dist/ws/dashboard-context-handler.d.ts +10 -15
  156. package/dist/ws/dashboard-fleet-handler.d.ts +4 -3
  157. package/dist/ws/dashboard-fleet-write-handler.d.ts +6 -5
  158. package/dist/ws/dashboard-global-workflows-handler.d.ts +1 -6
  159. package/dist/ws/dashboard-registrations-handler.d.ts +1 -7
  160. package/dist/ws/platform-client.d.ts +94 -327
  161. package/installer-image-digests.json +3 -3
  162. package/package.json +4 -4
  163. package/sbom.spdx.json +53 -53
  164. package/dist/cache/legacy-prefixes.d.ts +0 -19
  165. package/dist/cli/commands/agent-service/logs.d.ts +0 -14
  166. package/dist/cli/commands/agent-service/restart.d.ts +0 -12
  167. package/dist/cli/commands/agent-service/start.d.ts +0 -12
  168. package/dist/cli/commands/agent-service/stop.d.ts +0 -12
  169. package/dist/cli/commands/agent-service/uninstall.d.ts +0 -13
  170. package/dist/cli/commands/cache.d.ts +0 -51
  171. package/dist/cli/commands/orchestrator-service/logs.d.ts +0 -14
  172. package/dist/cli/commands/orchestrator-service/restart.d.ts +0 -12
  173. package/dist/cli/commands/orchestrator-service/start.d.ts +0 -12
  174. package/dist/cli/commands/orchestrator-service/stop.d.ts +0 -12
  175. package/dist/cli/commands/orchestrator-service/uninstall.d.ts +0 -13
  176. package/dist/git/inherited-secret.d.ts +0 -29
@@ -16,15 +16,10 @@
16
16
  * a failed build retries on the next boot.
17
17
  *
18
18
  * A repository check enforces that new indexes on those tables land here
19
- * rather than in a migration.
19
+ * rather than in a migration. The build itself is `deferred-index-build.ts`;
20
+ * this module holds only the list, so a CLI can read it without loading the
21
+ * orchestrator's metrics.
20
22
  */
21
- import type pg from 'pg';
22
- import { type Logger } from '@kici-dev/shared';
23
- /**
24
- * Distinct from the migrator's `543210001`: an index build must not block, or
25
- * be blocked by, a peer applying migrations.
26
- */
27
- export declare const DEFERRED_INDEX_LOCK_KEY = 543210002;
28
23
  export interface DeferredIndex {
29
24
  /** Index name, matching the one the SQL creates. */
30
25
  name: string;
@@ -40,33 +35,4 @@ export interface DeferredIndex {
40
35
  * prefixed by an organization or routing key.
41
36
  */
42
37
  export declare const DEFERRED_INDEXES: ReadonlyArray<DeferredIndex>;
43
- /**
44
- * Drop a leftover invalid index before rebuilding it.
45
- *
46
- * An interrupted `CREATE INDEX CONCURRENTLY` leaves the index in place marked
47
- * invalid: it is not used by the planner, and `IF NOT EXISTS` sees it and
48
- * skips. Without this, the very first failed build would make the retry a
49
- * permanent no-op — the opposite of the "retries on the next boot" contract.
50
- */
51
- export declare function dropIfInvalid(client: Pick<pg.Client, 'query'>, name: string, logger: Logger): Promise<void>;
52
- export interface BuildDeferredIndexesResult {
53
- built: string[];
54
- failed: string[];
55
- }
56
- /**
57
- * Build every deferred index on one dedicated connection.
58
- *
59
- * The connection is taken straight from `pg` rather than from the serving
60
- * pool: `CREATE INDEX CONCURRENTLY` must run outside a transaction and must
61
- * not inherit a statement timeout, and a concurrent build on a large table
62
- * would otherwise hold a serving connection for its whole duration.
63
- *
64
- * The advisory lock is `pg_try_advisory_lock`, not the blocking form: when a
65
- * peer is already building, this instance has nothing to wait for.
66
- */
67
- export declare function buildDeferredIndexes(databaseUrl: string, opts?: {
68
- logger?: Logger;
69
- indexes?: ReadonlyArray<DeferredIndex>;
70
- pg?: typeof import('pg');
71
- }): Promise<BuildDeferredIndexesResult>;
72
38
  //# sourceMappingURL=deferred-indexes.d.ts.map
@@ -8,11 +8,9 @@ import { type Kysely } from 'kysely';
8
8
  * unknown-type badge — and two semantically identical wait holds render
9
9
  * differently depending on which gate produced them.
10
10
  *
11
- * Writers emit the gate vocabulary; this backfills the history. The read path
12
- * also normalizes (`normalizePersistedHoldType`) and the wait-hold release
13
- * sweep matches both spellings, so a row written by an un-upgraded
14
- * orchestrator behaves correctly whether or not this has run — the two sides
15
- * deploy independently.
11
+ * Writers emit the gate vocabulary; this backfills the history. Migration 158
12
+ * re-applies the same rewrite, after which the readers match the gate
13
+ * vocabulary only.
16
14
  *
17
15
  * Idempotent: a second run matches no rows.
18
16
  */
@@ -0,0 +1,21 @@
1
+ import { type Kysely } from 'kysely';
2
+ /**
3
+ * Add `host_roster.identity_source text NOT NULL DEFAULT 'operator'`, limited
4
+ * to `agent`, `operator` and `platform`.
5
+ *
6
+ * It records who last set a host's identity (labels, hostname, properties):
7
+ * the host's own agent registration, a local `kici-admin host declare`, or a
8
+ * Platform-relayed dashboard declare. A `platform` row is an unconfirmed
9
+ * placeholder that fan-out, inventory and the unreachable alarm skip.
10
+ *
11
+ * Backfill: a row whose `platform` column is set has registered at least once
12
+ * (only an agent registration writes `platform`), so it becomes `agent`. Every
13
+ * other row stays `operator`: a dashboard-created row from before this column
14
+ * cannot be told apart from a `kici-admin` declare, and treating it as
15
+ * `platform` would drop every declared, never-connected host out of fan-out.
16
+ *
17
+ * Idempotent: a re-run on a database that already has the column is a no-op.
18
+ */
19
+ export declare function up(db: Kysely<unknown>): Promise<void>;
20
+ export declare function down(db: Kysely<unknown>): Promise<void>;
21
+ //# sourceMappingURL=157_host_roster_identity_source.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { type Kysely } from 'kysely';
2
+ export declare function up(db: Kysely<unknown>): Promise<void>;
3
+ export declare function down(): Promise<void>;
4
+ //# sourceMappingURL=158_normalize_legacy_values.d.ts.map
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The org ids this orchestrator holds data for, and which data names each one.
3
+ *
4
+ * The org-scoped kici-admin commands (`secret`, `context`, `variable`,
5
+ * `remote-source`, `org-settings`, `trust-policy`, `registration`) take an org
6
+ * id. This module answers "which org ids exist here" from the configuration and
7
+ * anchor tables, for both `GET /api/v1/admin/org-ids` and
8
+ * `kici-admin org list --database-url`, so the two transports cannot disagree.
9
+ */
10
+ import { type Kysely } from 'kysely';
11
+ import { z } from 'zod';
12
+ import type { Database } from '../types.js';
13
+ /**
14
+ * Where an org id was found. `platform` is the live Platform connection, which
15
+ * only the admin API can see; every other value names a table.
16
+ */
17
+ export declare const OrgIdSource: z.ZodEnum<{
18
+ context: "context";
19
+ "generic-source": "generic-source";
20
+ "org-settings": "org-settings";
21
+ platform: "platform";
22
+ registration: "registration";
23
+ "remote-source": "remote-source";
24
+ secret: "secret";
25
+ source: "source";
26
+ "trust-policy": "trust-policy";
27
+ }>;
28
+ export type OrgIdSource = z.infer<typeof OrgIdSource>;
29
+ /**
30
+ * The orchestrator's Platform attachment: `attached` once the Platform named
31
+ * the org on `auth.success`, `pending` while a Platform client has not
32
+ * authenticated yet, `none` when no Platform client runs (independent mode).
33
+ */
34
+ export declare const PlatformAttachment: z.ZodEnum<{
35
+ attached: "attached";
36
+ none: "none";
37
+ pending: "pending";
38
+ }>;
39
+ export type PlatformAttachment = z.infer<typeof PlatformAttachment>;
40
+ /** One org id and the data that names it. */
41
+ export interface HeldOrg {
42
+ orgId: string;
43
+ sources: OrgIdSource[];
44
+ }
45
+ /**
46
+ * Body of `GET /api/v1/admin/org-ids`. The two Platform fields are absent when the
47
+ * listing was read from the database directly: only the running orchestrator
48
+ * knows its connection.
49
+ */
50
+ export interface OrgListResponse {
51
+ platformAttachment?: PlatformAttachment;
52
+ attachedOrgId?: string | null;
53
+ orgs: HeldOrg[];
54
+ }
55
+ /** The admin API path of the listing. */
56
+ export declare const ORG_LIST_PATH = "/api/v1/admin/org-ids";
57
+ interface OrgIdTable {
58
+ table: keyof Database;
59
+ column: 'org_id' | 'customer_id';
60
+ source: Exclude<OrgIdSource, 'platform'>;
61
+ /** Skip soft-deleted rows (`deleted_at IS NULL`). */
62
+ liveOnly?: boolean;
63
+ }
64
+ /** The configuration and anchor tables an org-scoped command reads by org id. */
65
+ export declare const ORG_ID_TABLES: readonly OrgIdTable[];
66
+ /**
67
+ * Every other table with an `org_id` or `customer_id` column, and why the
68
+ * listing does not read it. A schema test fails when a migration adds an
69
+ * org-keyed table that is in neither this map nor {@link ORG_ID_TABLES}.
70
+ */
71
+ export declare const ORG_ID_TABLES_NOT_LISTED: Readonly<Record<string, string>>;
72
+ /** Group `(org id, source)` rows per org: org ids in byte order, sources in enum order. */
73
+ export declare function groupOrgIdRows(rows: ReadonlyArray<{
74
+ org_id: string;
75
+ source: OrgIdSource;
76
+ }>): HeldOrg[];
77
+ /** Add the Platform-attached org to a listing, with the `platform` source. */
78
+ export declare function withPlatformOrg(orgs: readonly HeldOrg[], attachedOrgId: string | null): HeldOrg[];
79
+ /** The attachment the admin API reports, from the Platform client's org id reader. */
80
+ export declare function readPlatformAttachment(getPlatformOrgId: (() => string | undefined) | undefined): {
81
+ platformAttachment: PlatformAttachment;
82
+ attachedOrgId: string | null;
83
+ };
84
+ /** Every org id the listed tables hold, in one round trip. */
85
+ export declare function listHeldOrgIds(db: Kysely<Database>): Promise<HeldOrg[]>;
86
+ export {};
87
+ //# sourceMappingURL=org-ids-repo.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { SchemaFingerprint } from '@kici-dev/shared';
2
+ export declare const SCHEMA_SNAPSHOT: SchemaFingerprint;
3
+ //# sourceMappingURL=schema-snapshot.generated.d.ts.map
@@ -13,6 +13,17 @@ export declare enum JobKind {
13
13
  Gate = "gate",
14
14
  Proxy = "proxy"
15
15
  }
16
+ /**
17
+ * Who last set a roster host's identity (labels, hostname, properties).
18
+ * `platform` marks an unconfirmed placeholder created from the dashboard: it
19
+ * is never a fan-out, inventory, agent-pin or unreachable-alarm target until
20
+ * its agent registers (`agent`) or an operator declares it (`operator`).
21
+ */
22
+ export declare enum HostIdentitySource {
23
+ agent = "agent",
24
+ operator = "operator",
25
+ platform = "platform"
26
+ }
16
27
  /**
17
28
  * PostgreSQL-only database types.
18
29
  * Column names use snake_case matching the actual database column names.
@@ -187,8 +198,9 @@ export type ClusterMeta = Selectable<ClusterMetaTable>;
187
198
  export type NewClusterMeta = Insertable<ClusterMetaTable>;
188
199
  /**
189
200
  * Join tokens table
190
- * Stores hashed join tokens for zero-knowledge cluster bootstrap.
191
- * Tokens are one-time use (consumed_at set after validation).
201
+ * Stores hashed join tokens. `kici-admin join` and peer token mode find a row by
202
+ * its hash; a token is consumed on first use and re-usable by the instance that
203
+ * consumed it until it expires.
192
204
  */
193
205
  export interface JoinTokenTable {
194
206
  /** UUID primary key */
@@ -1200,8 +1212,7 @@ export interface HeldRunsTable {
1200
1212
  /**
1201
1213
  * Hold type — an engine `HoldType` member ('reviewer' | 'timer' |
1202
1214
  * 'concurrency' | 'security'). Stays `string` so a row written by a
1203
- * different orchestrator version is never rejected; read it through
1204
- * `normalizePersistedHoldType`.
1215
+ * different orchestrator version is never rejected.
1205
1216
  */
1206
1217
  hold_type: string;
1207
1218
  /** Hold status: 'pending' | 'approved' | 'rejected' | 'expired' | 'released' */
@@ -1232,7 +1243,8 @@ export interface HeldRunsTable {
1232
1243
  trigger_source: Generated<string>;
1233
1244
  /**
1234
1245
  * Normalized `ApprovalRequirement` (clauses + expiresAt + reason) the hold
1235
- * must satisfy. Null for legacy rows that predate the approval model.
1246
+ * must satisfy. Null for a hold with no requirement: security, wait and queue
1247
+ * holds, which `security-hold-check.ts` tells apart on this column.
1236
1248
  */
1237
1249
  approval_requirement: ColumnType<ApprovalRequirement | null, ApprovalRequirement | string | null | undefined, ApprovalRequirement | string | null>;
1238
1250
  /**
@@ -2070,25 +2082,8 @@ export interface OrgTrustPolicyTable {
2070
2082
  customer_id: string;
2071
2083
  /** How to treat a pull request opened from a fork: ignore | hold | allow */
2072
2084
  fork_policy: string;
2073
- /**
2074
- * The coarse, hours-granularity view of the security-hold window.
2075
- *
2076
- * Retained and always written, because it is the only window an older peer or
2077
- * CLI can read. This build derives it from `approval_expiry_seconds` on every
2078
- * write (rounded up, never below 1), so the two columns cannot disagree.
2079
- */
2080
- approval_expiry_hours: number;
2081
- /**
2082
- * How long a security hold stays approvable before it expires, in seconds —
2083
- * the authoritative window, and the only granularity that can express a
2084
- * sub-hour hold.
2085
- *
2086
- * Nullable: NULL means no seconds value was ever written (a row predating the
2087
- * column, or one written by an older build), and every reader falls back to
2088
- * `approval_expiry_hours * 3600`. Same convention as
2089
- * `contexts.hold_expiry_seconds`.
2090
- */
2091
- approval_expiry_seconds: ColumnType<number | null, number | null | undefined, number | null>;
2085
+ /** How long a security hold stays approvable before it expires, in seconds. */
2086
+ approval_expiry_seconds: number;
2092
2087
  /** Which side last wrote this row: platform | local */
2093
2088
  source: string;
2094
2089
  /** When this policy was last written */
@@ -2839,6 +2834,8 @@ export interface HostRosterTable {
2839
2834
  * presigned URL). NULL / false ⇒ the conservative `ssh-push` fallback.
2840
2835
  */
2841
2836
  s3_reachable: ColumnType<boolean | null, boolean | null | undefined, boolean | null>;
2837
+ /** Who last set the host's identity. See {@link HostIdentitySource}. */
2838
+ identity_source: ColumnType<HostIdentitySource, HostIdentitySource | undefined, HostIdentitySource>;
2842
2839
  created_at: Generated<Date>;
2843
2840
  updated_at: ColumnType<Date, Date | string | undefined, Date | string>;
2844
2841
  }
@@ -9,7 +9,6 @@
9
9
  * TS2307s. Only the declaration lives here — its one dependency is a type from
10
10
  * `@kici-dev/engine`, so nothing test-only is pulled along with it.
11
11
  */
12
- import type { OrchCapabilities } from '@kici-dev/engine';
13
12
  /**
14
13
  * The set of synthetic faults a test-only entrypoint can inject into the
15
14
  * orchestrator. Every field is optional: an absent field means "no fault at
@@ -44,10 +43,5 @@ export interface OrchestratorFaultInjection {
44
43
  * the first coordinator slow enough that the Platform relay fails over.
45
44
  */
46
45
  beforeRerun?: () => Promise<void>;
47
- /**
48
- * Transform the advertised capability manifest — used to reproduce an older
49
- * / sourceless orchestrator that predates a given dashboard capability.
50
- */
51
- capabilitiesTransform?: (c: OrchCapabilities) => OrchCapabilities;
52
46
  }
53
47
  //# sourceMappingURL=fault-injection-types.d.ts.map
@@ -2,21 +2,15 @@ import type { ProviderGitAuth } from '@kici-dev/engine';
2
2
  import type { ProviderBundle, ProviderRegistry } from '../provider-registry.js';
3
3
  /** Auth the dispatch message carries; every field is optional on the wire. */
4
4
  export interface DispatchCloneAuth {
5
- /** Bare source-repository token, kept for agents that read only `token`. */
6
- token?: string;
7
5
  sourceAuth?: ProviderGitAuth;
8
6
  workflowAuth?: ProviderGitAuth;
9
7
  }
10
8
  /**
11
- * Mint structured auth (and a bare token when it is basic auth) for one
12
- * repository through one bundle. Providers that implement `issueGitAuth()`
13
- * return the auth kind directly; otherwise a clone token is wrapped in a
14
- * basic-auth envelope.
9
+ * Mint structured auth for one repository through one bundle. Providers that
10
+ * implement `issueGitAuth()` return the auth kind directly; otherwise a clone
11
+ * token is wrapped in a basic-auth envelope.
15
12
  */
16
- export declare function mintRepoGitAuth(bundle: ProviderBundle, repoIdentifier: string, providerContext: unknown): Promise<{
17
- token: string | null;
18
- structuredAuth: ProviderGitAuth | null;
19
- }>;
13
+ export declare function mintRepoGitAuth(bundle: ProviderBundle, repoIdentifier: string, providerContext: unknown): Promise<ProviderGitAuth | null>;
20
14
  /** The job fields the auth resolution reads. */
21
15
  export interface DispatchAuthJob {
22
16
  id: string;
@@ -35,8 +29,8 @@ export declare function gitHostOf(url: string): string | undefined;
35
29
  * it may.
36
30
  *
37
31
  * The agent falls back across the two clones: it clones the source repository
38
- * with `sourceAuth ?? workflowAuth ?? token` and the workflow repository with
39
- * `workflowAuth ?? sourceAuth ?? token`. When only one repository's credential is
32
+ * with `sourceAuth ?? workflowAuth` and the workflow repository with
33
+ * `workflowAuth ?? sourceAuth`. When only one repository's credential is
40
34
  * present, the other clone sends it to that repository's host. On the same host
41
35
  * that is a credential the host issued; on another host it hands one provider's
42
36
  * credential to another, so the job is refused instead. A job with no source URL
@@ -10,11 +10,17 @@
10
10
  * the Platform `webhook_sources` row and the dashboard Sources tab pick up the
11
11
  * new name/slug without any extra plumbing here.
12
12
  *
13
+ * The same pass checks each App against the events and permissions KiCI needs
14
+ * (`GITHUB_APP_REQUIREMENTS`) and the permissions each installation has
15
+ * accepted, and logs one warning per App with gaps. A gap never blocks the name
16
+ * and slug sync.
17
+ *
13
18
  * Lifecycle mirrors `StaleRunDetector`: `start()` runs an immediate refresh
14
19
  * (so a rename made while the orchestrator was down propagates on next boot)
15
20
  * then a `setInterval`; `stop()` clears it. Per-source errors are logged and
16
21
  * never abort the loop.
17
22
  */
23
+ import { type GithubAppIdentity, type GithubAppInstallationGrant, type GithubAppRequirementGaps } from '../providers/github/manifest.js';
18
24
  /** A source row as returned by listSources() — the slice this module needs. */
19
25
  export type SourceIdentityRow = {
20
26
  routing_key: string;
@@ -39,12 +45,14 @@ export interface RefreshableSourceStore {
39
45
  export type FetchGithubAppIdentity = (creds: {
40
46
  appId: string;
41
47
  privateKey: string;
42
- }) => Promise<{
43
- name: string;
44
- slug: string;
45
- }>;
46
- /** Outcome of a single source refresh. */
47
- export interface RefreshResult {
48
+ }) => Promise<GithubAppIdentity>;
49
+ /** List a GitHub App's installations. Matches `listGithubAppInstallations`. */
50
+ export type FetchGithubAppInstallations = (creds: {
51
+ appId: string;
52
+ privateKey: string;
53
+ }) => Promise<GithubAppInstallationGrant[]>;
54
+ /** Outcome of a single source refresh: the name and slug sync plus the requirement gaps. */
55
+ export interface RefreshResult extends GithubAppRequirementGaps {
48
56
  routingKey: string;
49
57
  changed: boolean;
50
58
  oldName: string;
@@ -54,27 +62,31 @@ export interface RefreshResult {
54
62
  }
55
63
  /**
56
64
  * Refresh one already-resolved GitHub source's identity from GitHub and persist
57
- * it when the name or slug drifted. The caller supplies the row it already holds,
58
- * so this never lists the sources table. Throws for a non-GitHub row or missing
59
- * credentials.
65
+ * it when the name or slug drifted, then compare the App and its installations
66
+ * with the required events and permissions. The caller supplies the row it
67
+ * already holds, so this never lists the sources table. Throws for a non-GitHub
68
+ * row or missing credentials. A failed installations listing throws after the
69
+ * name and slug sync has been written, so the sync never waits on the gap check.
60
70
  */
61
- export declare function refreshResolvedGithubSource(sourceStore: Pick<RefreshableSourceStore, 'getSourceWithSecrets' | 'updateSource'>, row: SourceIdentityRow, fetchIdentity: FetchGithubAppIdentity): Promise<RefreshResult>;
71
+ export declare function refreshResolvedGithubSource(sourceStore: Pick<RefreshableSourceStore, 'getSourceWithSecrets' | 'updateSource'>, row: SourceIdentityRow, fetchIdentity: FetchGithubAppIdentity, fetchInstallations: FetchGithubAppInstallations): Promise<RefreshResult>;
62
72
  /**
63
73
  * Re-fetch one GitHub source's identity from GitHub and persist it when the
64
- * name or slug drifted. Resolves the row by routing key (one sources read) then
65
- * delegates. Shared by `kici-admin source refresh`. Throws for a missing or
74
+ * name or slug drifted, and report requirement gaps. Resolves the row by routing
75
+ * key (one sources read) then delegates. Shared by `kici-admin source refresh`. Throws for a missing or
66
76
  * non-GitHub routing key.
67
77
  */
68
- export declare function refreshGithubSourceIdentity(sourceStore: RefreshableSourceStore, routingKey: string, fetchIdentity: FetchGithubAppIdentity): Promise<RefreshResult>;
78
+ export declare function refreshGithubSourceIdentity(sourceStore: RefreshableSourceStore, routingKey: string, fetchIdentity: FetchGithubAppIdentity, fetchInstallations: FetchGithubAppInstallations): Promise<RefreshResult>;
69
79
  export interface GithubAppNameRefresherDeps {
70
80
  sourceStore: RefreshableSourceStore;
71
81
  fetchIdentity: FetchGithubAppIdentity;
82
+ fetchInstallations: FetchGithubAppInstallations;
72
83
  /** Refresh cadence in ms. Default cluster value: 24h (`config.githubAppNameRefreshIntervalMs`). */
73
84
  scanIntervalMs: number;
74
85
  }
75
86
  export declare class GithubAppNameRefresher {
76
87
  private readonly sourceStore;
77
88
  private readonly fetchIdentity;
89
+ private readonly fetchInstallations;
78
90
  private readonly scanIntervalMs;
79
91
  private interval;
80
92
  constructor(deps: GithubAppNameRefresherDeps);
@@ -0,0 +1,3 @@
1
+ /** Parse JSON, returning null for empty, nullish or invalid input. */
2
+ export declare function safeJsonParse(value: string | null | undefined): unknown;
3
+ //# sourceMappingURL=json.d.ts.map
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export { SourceCache } from './cache/source-cache.js';
5
5
  export { DepCache } from './cache/dep-cache.js';
6
6
  export { UserCache, DEFAULT_USER_CACHE_QUOTA_BYTES, DEFAULT_USER_CACHE_TTL_MS, type UserCacheRef, type UserCacheRestoreResult, type UserCacheBeginSaveResult, } from './cache/user-cache.js';
7
7
  export { PeerCredentialStore, createPeerCredentialStoreFromUrl, type PeerCredential, type CredentialFileData, } from './cluster/peer-credentials.js';
8
- export { PeerAuthCoordinator, type AuthDecision, type RejectionAction, } from './cluster/peer-auth-coordinator.js';
8
+ export { PeerAuthCoordinator, RejectionAction, type AuthDecision, } from './cluster/peer-auth-coordinator.js';
9
9
  export { JoinTokenManager, createJoinTokenManagerFromUrl } from './cluster/join-token.js';
10
10
  export { HeldRunStore, createHeldRunStoreFromUrl, SecurityHoldReason, } from './contexts/held-runs.js';
11
11
  export { TrustPolicyStore, createTrustPolicyStoreFromUrl, TrustPolicySource, DEFAULT_TRUST_POLICY, type StoredTrustPolicy, } from './security/trust-policy-store.js';