@kici-dev/orchestrator 0.1.16 → 0.1.17

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 (58) hide show
  1. package/dist/agent/dispatcher.d.ts +18 -1
  2. package/dist/approvals/apply-decision.d.ts +11 -1
  3. package/dist/cache/pending-inits.d.ts +5 -0
  4. package/dist/cli/api-client.d.ts +11 -0
  5. package/dist/cli/commands/local-hook.d.ts +15 -0
  6. package/dist/cli/commands/local-trigger.d.ts +24 -0
  7. package/dist/cli/commands/remote-source.d.ts +17 -0
  8. package/dist/cli/commands/shared/versioned-upgrade.d.ts +14 -0
  9. package/dist/cli/kici-admin.d.ts +13 -0
  10. package/dist/cli.js +726 -177
  11. package/dist/config.d.ts +0 -4
  12. package/dist/dashboard/handler.d.ts +26 -2
  13. package/dist/dashboard/needs-edges.d.ts +13 -0
  14. package/dist/db/migrations/035_pending_workflow_contexts.d.ts +11 -0
  15. package/dist/db/migrations/036_attestations.d.ts +15 -0
  16. package/dist/db/migrations/037_generic_sources_provider_type_local.d.ts +19 -0
  17. package/dist/db/migrations/038_remote_sources.d.ts +14 -0
  18. package/dist/db/types.d.ts +83 -10
  19. package/dist/diagnostics/fleet-collector.d.ts +1 -1
  20. package/dist/entry-helpers.d.ts +7 -29
  21. package/dist/environments/held-runs.d.ts +24 -0
  22. package/dist/index.js +1 -0
  23. package/dist/metrics/prometheus.d.ts +4 -2
  24. package/dist/orchestrator-core.d.ts +48 -0
  25. package/dist/pipeline/dispatch-matched-workflow.d.ts +18 -1
  26. package/dist/pipeline/install-secrets-resolver.d.ts +32 -5
  27. package/dist/pipeline/needs-scheduler.d.ts +12 -10
  28. package/dist/pipeline/pending-workflow-context.d.ts +44 -0
  29. package/dist/pipeline/processor.d.ts +6 -4
  30. package/dist/pipeline/remote-source-store.d.ts +21 -0
  31. package/dist/pipeline/resume-workflow.d.ts +26 -0
  32. package/dist/providers/local/index.d.ts +33 -0
  33. package/dist/providers/local/local-source-config.d.ts +17 -0
  34. package/dist/providers/{internal → local}/lock-file-fetcher.d.ts +6 -6
  35. package/dist/providers/{internal → local}/normalizer.d.ts +28 -28
  36. package/dist/providers/{internal → local}/repo-url-builder.d.ts +6 -6
  37. package/dist/reporting/execution-tracker.d.ts +33 -0
  38. package/dist/routes/admin-events.d.ts +3 -4
  39. package/dist/routes/uploads.d.ts +36 -26
  40. package/dist/server.js +27910 -26483
  41. package/dist/sources/build-platform-sources.d.ts +4 -2
  42. package/dist/stale-detector/stale-run-detector.d.ts +14 -1
  43. package/dist/standalone.js +15708 -15619
  44. package/dist/webhook/generic-sources-listener.d.ts +4 -0
  45. package/dist/webhook/generic-sources.d.ts +37 -11
  46. package/dist/webhook/register-source-bundle.d.ts +14 -4
  47. package/dist/ws/agent-handler.d.ts +17 -0
  48. package/dist/ws/dashboard-dispatch-guard.d.ts +21 -0
  49. package/dist/ws/dashboard-env-handler.d.ts +13 -1
  50. package/dist/ws/oidc-token-relay.d.ts +59 -0
  51. package/dist/ws/platform-client.d.ts +30 -1
  52. package/dist/ws/test-relay-handlers.d.ts +112 -0
  53. package/installer-image-digests.json +3 -3
  54. package/package.json +4 -4
  55. package/sbom.spdx.json +98 -48
  56. package/dist/providers/internal/index.d.ts +0 -32
  57. package/dist/routes/test-trigger.d.ts +0 -41
  58. package/dist/ws/observer-handler.d.ts +0 -42
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pending workflow dispatch context store — the workflow-level analogue of the
3
+ * `pending_job_contexts` store. Persists the serializable inputs of a
4
+ * `WorkflowDispatchContext` so a workflow whose install gate held can be
5
+ * resumed (reviewer approve, wait-timer expiry, concurrency slot free) by
6
+ * rebuilding the dispatch context and re-running `dispatchMatchedWorkflow`.
7
+ *
8
+ * Only the serializable inputs are stored — the live `deps` (ProcessingDeps)
9
+ * and `bundle` (ProviderBundle) are NOT persisted; they are rebuilt from the
10
+ * live orchestrator on resume.
11
+ *
12
+ * Writes to both an in-memory Map (fast read on the same process) and the DB
13
+ * (crash recovery + cross-orchestrator read), mirroring the pending-job store.
14
+ */
15
+ import type { Kysely } from 'kysely';
16
+ import type { Database } from '../db/types.js';
17
+ import type { WorkflowDispatchContext } from './dispatch-matched-workflow.js';
18
+ /**
19
+ * The serializable subset of a `WorkflowDispatchContext` — everything except
20
+ * the live `deps` and `bundle`, which are rebuilt on resume. Every field here
21
+ * is JSON-safe (the event, payload, and lock file already ride the WS protocol
22
+ * as JSON).
23
+ */
24
+ export type SerializableWorkflowDispatchInputs = Omit<WorkflowDispatchContext, 'deps' | 'bundle'>;
25
+ /** Extract the serializable inputs from a live dispatch context. */
26
+ export declare function toSerializableInputs(ctx: WorkflowDispatchContext): SerializableWorkflowDispatchInputs;
27
+ /** Persist the pending workflow context to the in-memory Map and the DB. */
28
+ export declare function storePendingWorkflowContext(db: Kysely<Database> | undefined, inputs: SerializableWorkflowDispatchInputs): Promise<void>;
29
+ /** Load the pending workflow context by run id (memory first, then DB). */
30
+ export declare function loadPendingWorkflowContext(db: Kysely<Database> | undefined, runId: string): Promise<SerializableWorkflowDispatchInputs | null>;
31
+ /** Delete the pending workflow context from the in-memory Map and the DB. */
32
+ export declare function deletePendingWorkflowContext(db: Kysely<Database> | undefined, runId: string): Promise<void>;
33
+ /**
34
+ * Restore the in-memory Map from the DB on startup, skipping rows whose run has
35
+ * already reached a terminal state. Mirrors `restorePendingJobContexts`.
36
+ * Returns the number of restored contexts.
37
+ */
38
+ export declare function restorePendingWorkflowContexts(db: Kysely<Database>): Promise<number>;
39
+ /**
40
+ * Clear all entries from the in-memory pending workflow contexts Map.
41
+ * @internal Exported for testing only.
42
+ */
43
+ export declare function clearPendingWorkflowContextsMap(): void;
44
+ //# sourceMappingURL=pending-workflow-context.d.ts.map
@@ -112,7 +112,7 @@ export declare function isRootJob(lockJob: LockJob): boolean;
112
112
  * Why this exists
113
113
  * ----------------
114
114
  * The webhook pipeline binds `lockFileFetcher` to the inbound webhook's
115
- * provider bundle. When an internal-sourced webhook (e.g., the staging
115
+ * provider bundle. When a local-sourced webhook (e.g., the staging
116
116
  * stg-ha-smoke failover-dispatch test) arrives for a repo whose lock file
117
117
  * is only accessible via a different provider (e.g., github), the inbound
118
118
  * fetcher returns null and trigger matching silently drops the webhook.
@@ -143,7 +143,7 @@ export declare function isRootJob(lockJob: LockJob): boolean;
143
143
  * -----------
144
144
  * Each fallback fetcher is invoked with the REGISTRATION'S
145
145
  * `providerContext`, NOT the inbound normalizer's credentials. This is
146
- * load-bearing: the InternalWebhookNormalizer returns `{}` as
146
+ * load-bearing: the LocalWebhookNormalizer returns `{}` as
147
147
  * credentials, which would never satisfy a github fetcher that requires
148
148
  * `installationId`. The registration carries the correct credentials
149
149
  * because it was created via the owning provider's source.
@@ -178,8 +178,10 @@ export declare function resolveLockFileWithFallback(args: {
178
178
  * Resolve the customer/org ID for a routing key.
179
179
  *
180
180
  * Checks the `sources` table first (GitHub App sources), then
181
- * `generic_webhook_sources` (generic webhook sources). Falls back to
182
- * '__default__' if neither table has the routing key.
181
+ * `generic_webhook_sources` (generic webhook sources), then `remote_sources`
182
+ * (the auto-provisioned anchor for Platform-relayed `kici run remote`, routing
183
+ * key `remote:<orgId>`). Falls back to '__default__' if none of the three
184
+ * tables has the routing key.
183
185
  */
184
186
  export declare function resolveOrgId(db: Kysely<Database>, routingKey: string): Promise<string>;
185
187
  /**
@@ -0,0 +1,21 @@
1
+ import type { Kysely } from 'kysely';
2
+ import type { Database, RemoteSourceRow } from '../db/types.js';
3
+ /**
4
+ * Deterministic routing key for an org's Platform-relayed remote runs. A
5
+ * Platform-relayed `test.trigger` carries this key; `resolveOrgId` maps it back
6
+ * to the canonical org id via the `remote_sources` row.
7
+ */
8
+ export declare function remoteRoutingKeyFor(orgId: string): string;
9
+ /**
10
+ * Idempotently upsert the `remote_sources` anchor for an org. Called on every
11
+ * Platform (re)connect once the orchestrator learns its canonical org id from
12
+ * `auth.success`. The unique `(customer_id)` constraint makes this a safe
13
+ * self-heal — re-running updates `cluster_id` if the cluster identity changed.
14
+ */
15
+ export declare function provisionRemoteSource(db: Kysely<Database>, params: {
16
+ orgId: string;
17
+ clusterId: string | null;
18
+ }): Promise<void>;
19
+ /** Read the auto-provisioned remote-source row for an org, if it exists. */
20
+ export declare function getRemoteSource(db: Kysely<Database>, orgId: string): Promise<RemoteSourceRow | undefined>;
21
+ //# sourceMappingURL=remote-source-store.d.ts.map
@@ -0,0 +1,26 @@
1
+ import type { Kysely } from 'kysely';
2
+ import type { Database } from '../db/types.js';
3
+ import type { ProcessingDeps } from './processor.js';
4
+ import type { ReleaseSignal } from '../environments/held-runs.js';
5
+ import { type WorkflowDispatchContext } from './dispatch-matched-workflow.js';
6
+ import { type SerializableWorkflowDispatchInputs } from './pending-workflow-context.js';
7
+ /**
8
+ * Rebuild a live `WorkflowDispatchContext` from the persisted serializable
9
+ * inputs by re-attaching the orchestrator's live `deps` and reconstructing the
10
+ * provider `bundle` from the live registry (keyed by the stored routing key).
11
+ * Returns null when the provider bundle can no longer be resolved.
12
+ */
13
+ export declare function rebuildWorkflowDispatchContext(inputs: SerializableWorkflowDispatchInputs, deps: ProcessingDeps): WorkflowDispatchContext | null;
14
+ /**
15
+ * Resume a released workflow install-gate hold. Loads the pending context,
16
+ * rebuilds the dispatch context, and re-dispatches with the gate skipped. On a
17
+ * lost pending context (or unresolvable provider bundle) the run is failed
18
+ * loudly rather than silently dropped.
19
+ */
20
+ export declare function resumeWorkflow(signal: ReleaseSignal, deps: ProcessingDeps, db: Kysely<Database> | undefined): Promise<void>;
21
+ /**
22
+ * Cancel a rejected workflow install-gate hold: mark the run cancelled and drop
23
+ * the pending context.
24
+ */
25
+ export declare function rejectWorkflow(runId: string, deps: ProcessingDeps, db: Kysely<Database> | undefined, reason: string): Promise<void>;
26
+ //# sourceMappingURL=resume-workflow.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Local filesystem (`file://`) source provider implementations.
3
+ *
4
+ * Provides a complete provider bundle for cloning a git repository that is
5
+ * already present on the agent's filesystem, with no remote forge, no webhook
6
+ * signature verification, and no network clone. Uses file:// URLs for cloning
7
+ * and reads lock files directly from the filesystem.
8
+ *
9
+ * Classes:
10
+ * - LocalWebhookNormalizer -> WebhookNormalizer (extracts from custom headers)
11
+ * - LocalLockFileFetcher -> LockFileFetcher (reads from local filesystem)
12
+ * - LocalRepoUrlBuilder -> RepoUrlBuilder (returns file:// URLs)
13
+ */
14
+ import type { ProviderBundle } from '../../provider-registry.js';
15
+ export { LocalWebhookNormalizer } from './normalizer.js';
16
+ export { LocalLockFileFetcher } from './lock-file-fetcher.js';
17
+ export { LocalRepoUrlBuilder } from './repo-url-builder.js';
18
+ /**
19
+ * Create a ProviderBundle for a local filesystem (`file://`) source.
20
+ *
21
+ * Provides normalizer, lock file fetcher, and repo URL builder.
22
+ * Clone token provider and changed files fetcher are null since
23
+ * file:// URLs need no auth and local events don't track changed files.
24
+ *
25
+ * @param opts.repoBasePath - Base directory where the repo(s) live on disk
26
+ * @param opts.cloneUrlBase - Optional URL base for clone operations (e.g. git://host/path)
27
+ * @returns Complete ProviderBundle for the local provider
28
+ */
29
+ export declare function createLocalProviderBundle(opts: {
30
+ repoBasePath: string;
31
+ cloneUrlBase?: string;
32
+ }): ProviderBundle;
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Configuration for a local filesystem (`file://`) source, stored as JSONB in
3
+ * `generic_webhook_sources.git_config` and discriminated from universal-git
4
+ * config by the row's `provider_type='local'`.
5
+ *
6
+ * A local source clones a git repository that already exists on the agent's
7
+ * filesystem (host path for bare-metal scalers, image-bundled / rootfs /
8
+ * bind-mounted path for container + Firecracker scalers). The orchestrator does
9
+ * not verify in-agent reachability — that is the operator's responsibility.
10
+ */
11
+ import { z } from 'zod';
12
+ export declare const LocalSourceConfigSchema: z.ZodObject<{
13
+ repoBasePath: z.ZodString;
14
+ cloneUrlBase: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strict>;
16
+ export type LocalSourceConfig = z.infer<typeof LocalSourceConfigSchema>;
17
+ //# sourceMappingURL=local-source-config.d.ts.map
@@ -1,22 +1,22 @@
1
1
  /**
2
- * Internal lock file fetcher for E2E tests.
2
+ * Local filesystem lock file fetcher.
3
3
  *
4
4
  * Implements the LockFileFetcher interface from @kici-dev/engine by reading
5
- * kici.lock.json directly from the local filesystem. Used when the internal
5
+ * kici.lock.json directly from the local filesystem. Used when the local
6
6
  * provider processes webhooks for repos accessible via file:// URLs.
7
7
  */
8
8
  import type { LockFileFetcher, LockFile } from '@kici-dev/engine';
9
9
  /**
10
- * Internal provider implementation of LockFileFetcher.
10
+ * Local provider implementation of LockFileFetcher.
11
11
  *
12
12
  * Reads kici.lock.json from the local filesystem at the path derived from
13
13
  * the repoIdentifier (which is expected to be a file:// URL or a local path).
14
14
  */
15
- export declare class InternalLockFileFetcher implements LockFileFetcher {
15
+ export declare class LocalLockFileFetcher implements LockFileFetcher {
16
16
  private readonly repoBasePath;
17
- readonly provider: "internal";
17
+ readonly provider: "local";
18
18
  /**
19
- * @param repoBasePath - Base directory for test repos. When repoIdentifier
19
+ * @param repoBasePath - Base directory for the repo(s). When repoIdentifier
20
20
  * starts with 'file://', it is stripped and used as-is. Otherwise
21
21
  * repoBasePath is used as the root.
22
22
  */
@@ -1,25 +1,25 @@
1
1
  /**
2
- * Internal webhook normalizer for E2E tests.
2
+ * Local filesystem source webhook normalizer.
3
3
  *
4
- * Implements the WebhookNormalizer interface from @kici-dev/engine for internal
5
- * webhook sources. Used by the provider-agnostic E2E test suite to trigger the
6
- * full webhook processing pipeline without GitHub dependencies.
7
- *
8
- * Verification is always skipped (internal sources use verification='none').
9
- * Event type and routing key are extracted from custom headers.
4
+ * Implements the WebhookNormalizer interface from @kici-dev/engine for local
5
+ * (`file://`) sources. Drives the full webhook processing pipeline without a
6
+ * remote forge: signature verification is skipped (local sources use
7
+ * verification='none'), and event type / routing key are extracted from custom
8
+ * headers.
10
9
  */
11
10
  import type { WebhookNormalizer, SimulatedEvent, AccessCacheInvalidation } from '@kici-dev/engine';
12
11
  /**
13
- * Internal provider implementation of WebhookNormalizer.
12
+ * Local provider implementation of WebhookNormalizer.
14
13
  *
15
- * Maps internal webhook headers and payloads to KiCI's universal SimulatedEvent format.
16
- * Designed for E2E tests where payloads use normalized provider-agnostic structures
14
+ * Maps the synthetic webhook headers and payloads sent to a local source into
15
+ * KiCI's universal SimulatedEvent format. Payloads use the same GitHub-shaped
16
+ * structure the trigger CLI / post-receive hook build
17
17
  * (e.g., {ref: 'refs/heads/master', repository: {full_name: 'test/repo'}}).
18
18
  */
19
- export declare class InternalWebhookNormalizer implements WebhookNormalizer {
20
- readonly provider: "internal";
19
+ export declare class LocalWebhookNormalizer implements WebhookNormalizer {
20
+ readonly provider: "local";
21
21
  /**
22
- * Extract routing key from internal webhook headers.
22
+ * Extract routing key from the local-source webhook headers.
23
23
  *
24
24
  * Checks x-kici-routing-key first (explicit routing), then falls back
25
25
  * to x-kici-source-id (generic source ID format).
@@ -38,42 +38,42 @@ export declare class InternalWebhookNormalizer implements WebhookNormalizer {
38
38
  /**
39
39
  * Verify signature -- always returns true.
40
40
  *
41
- * Internal sources use verification='none'. Actual verification is not
42
- * needed for E2E test infrastructure where both sender and receiver
43
- * are controlled by the test harness.
41
+ * Local sources use verification='none' there is no remote forge to sign
42
+ * the payload. The operator is responsible for only registering repos they
43
+ * trust (see docs/user/providers/local-file.md).
44
44
  */
45
45
  verifySignature(_body: string, _headers: Record<string, string>, _secret: string): boolean;
46
46
  /**
47
- * Extract repository identifier from an internal webhook payload.
47
+ * Extract repository identifier from a local-source webhook payload.
48
48
  *
49
- * Internal events mimic GitHub-shaped payloads in E2E tests,
50
- * so we extract from payload.repository.full_name if present.
49
+ * Local-source events use GitHub-shaped payloads, so we extract from
50
+ * payload.repository.full_name if present.
51
51
  */
52
52
  extractRepoIdentifier(payload: unknown): string | null;
53
53
  /**
54
- * Extract ref from an internal webhook payload.
54
+ * Extract ref from a local-source webhook payload.
55
55
  *
56
- * Internal events use GitHub-shaped payloads, so extraction logic
56
+ * Local-source events use GitHub-shaped payloads, so extraction logic
57
57
  * mirrors GitHub's: push -> payload.after, PR -> payload.pull_request.head.sha.
58
58
  */
59
59
  extractRef(eventType: string, payload: unknown): string;
60
60
  /**
61
- * Extract credentials -- internal sources carry no provider credentials.
61
+ * Extract credentials -- local sources carry no provider credentials.
62
62
  */
63
63
  extractCredentials(_payload: unknown): Record<string, unknown>;
64
64
  /**
65
- * Normalize an internal webhook event into a SimulatedEvent.
65
+ * Normalize a local-source webhook event into a SimulatedEvent.
66
66
  *
67
67
  * Extracts branch information from payload.ref (stripping refs/heads/ prefix)
68
- * and preserves the raw payload for trigger matching. Falls back to '__internal__'
68
+ * and preserves the raw payload for trigger matching. Falls back to '__local__'
69
69
  * when no ref is present.
70
70
  */
71
71
  normalizeEvent(eventType: string, _action: string | null, payload: unknown): SimulatedEvent | null;
72
72
  /**
73
- * Map membership-related internal webhook events to ContributorCache
73
+ * Map membership-related local-source webhook events to ContributorCache
74
74
  * invalidations.
75
75
  *
76
- * Internal E2E payloads are GitHub-shaped by design, so the mapping
76
+ * Local-source payloads are GitHub-shaped by design, so the mapping
77
77
  * mirrors the GitHub normalizer exactly:
78
78
  *
79
79
  * - `member`: repo-user
@@ -81,8 +81,8 @@ export declare class InternalWebhookNormalizer implements WebhookNormalizer {
81
81
  * - `membership`: user-in-org
82
82
  * - `team` (repo-scoped actions only): repo
83
83
  *
84
- * This lets Bucket C E2E tests exercise the invalidation path through
85
- * `sendInternalWebhook()` without requiring a real GitHub App.
84
+ * This lets membership-invalidation paths be exercised through
85
+ * `sendLocalWebhook()` without requiring a real GitHub App.
86
86
  */
87
87
  getAccessCacheInvalidations(eventType: string, _action: string | null, payload: unknown): AccessCacheInvalidation[];
88
88
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Internal repo URL builder for E2E tests.
2
+ * Local filesystem repo URL builder.
3
3
  *
4
4
  * Implements the RepoUrlBuilder interface from @kici-dev/engine by returning
5
5
  * file:// URLs for local filesystem access, or network URLs (git://, http://)
@@ -7,16 +7,16 @@
7
7
  */
8
8
  import type { RepoUrlBuilder } from '@kici-dev/engine';
9
9
  /**
10
- * Internal provider implementation of RepoUrlBuilder.
10
+ * Local provider implementation of RepoUrlBuilder.
11
11
  *
12
12
  * Builds clone URLs for repository access. When cloneUrlBase is set (e.g. to
13
13
  * a git:// daemon URL), uses it for clone URLs so remote agents on different
14
14
  * machines can clone. Otherwise falls back to file:// URLs for local access.
15
15
  */
16
- export declare class InternalRepoUrlBuilder implements RepoUrlBuilder {
16
+ export declare class LocalRepoUrlBuilder implements RepoUrlBuilder {
17
17
  private readonly repoBasePath;
18
18
  private readonly cloneUrlBase?;
19
- readonly provider: "internal";
19
+ readonly provider: "local";
20
20
  /**
21
21
  * @param repoBasePath - Base directory where test repos live on disk
22
22
  * @param cloneUrlBase - Optional URL base for clone operations (e.g. git://host/path).
@@ -34,8 +34,8 @@ export declare class InternalRepoUrlBuilder implements RepoUrlBuilder {
34
34
  /**
35
35
  * Build a raw file URL -- returns empty string.
36
36
  *
37
- * Internal repos have no web UI, so raw file URLs are not applicable.
38
- * The lock file is fetched via InternalLockFileFetcher (filesystem) instead.
37
+ * Local repos have no web UI, so raw file URLs are not applicable.
38
+ * The lock file is fetched via LocalLockFileFetcher (filesystem) instead.
39
39
  */
40
40
  buildRawFileUrl(_repoIdentifier: string, _ref: string, _path: string): string;
41
41
  }
@@ -395,6 +395,39 @@ export declare class ExecutionTracker {
395
395
  triggerEvent?: string;
396
396
  commitMessage?: string;
397
397
  }): Promise<void>;
398
+ /**
399
+ * Record a run paused at the workflow install gate (a `registries:` /
400
+ * `installEnv:` protection rule returned hold / wait / queue). Writes an
401
+ * `execution_runs` row in the `held` state — alive and resumable — so the
402
+ * dashboard run list surfaces the paused workflow. No jobs are tracked: the
403
+ * workflow-scoped held_runs row + pending workflow context (written by the
404
+ * caller) keep the run from being counted complete. Idempotent on runId.
405
+ */
406
+ recordRunHeld(args: {
407
+ runId: string;
408
+ workflowName: string;
409
+ provider: string;
410
+ repoIdentifier: string;
411
+ ref: string;
412
+ sha: string;
413
+ deliveryId: string | null;
414
+ providerContext: Record<string, unknown>;
415
+ routingKey: string;
416
+ environmentName?: string;
417
+ reason: string;
418
+ triggerEvent?: string;
419
+ commitMessage?: string;
420
+ }): Promise<void>;
421
+ /**
422
+ * Flip a `held` run back to `pending` so the resumed dispatch can proceed
423
+ * into job dispatch. Returns true when a held row was found and updated.
424
+ */
425
+ resumeHeldRun(runId: string): Promise<boolean>;
426
+ /**
427
+ * Cancel a held run (reviewer rejected the install gate). Flips the held row
428
+ * to `cancelled` and fires the status-change forward so Platform projects it.
429
+ */
430
+ cancelHeldRun(runId: string, reason: string): Promise<void>;
398
431
  /**
399
432
  * Mark a run as failed immediately with a reason message.
400
433
  *
@@ -26,15 +26,14 @@ interface AdminEventRouteDeps {
26
26
  rbac: RbacEnforcer;
27
27
  /**
28
28
  * The in-process bundle registry. The POST /generic-sources handler
29
- * registers an internal / universal-git bundle into this registry
29
+ * registers a local / universal-git bundle into this registry
30
30
  * immediately after the source row lands in the DB, so the next
31
31
  * webhook against that source resolves the right normalizer without
32
32
  * waiting for an orchestrator restart.
33
33
  */
34
34
  providerRegistry: ProviderRegistry;
35
- /** Needed by `registerProviderBundleForSource` to gate internal-bundle
36
- * registration on `canServeGenericProviderType` and read the
37
- * `internalProviderRepoPath` / `internalProviderCloneUrl` config. */
35
+ /** Passed through to `registerProviderBundleForSource` (universal-git bundle
36
+ * build reads cluster config; local bundles read the row's own git_config). */
38
37
  config: AppConfig;
39
38
  /** Required for universal-git source registration — `null` is allowed;
40
39
  * rows with `git_config` are skipped + metric-bumped in that case. */
@@ -1,38 +1,48 @@
1
1
  /**
2
- * REST endpoints for test run upload management.
2
+ * Test-run upload provisioning.
3
3
  *
4
- * POST /api/v1/uploads/init - Initialize an upload (returns signed URL + public key)
5
- * GET /api/v1/uploads/:uploadId/status - Check upload status
6
- *
7
- * Uploads support the repo state transfer mechanism: CLI uploads an encrypted
8
- * tarball of changed files to S3 via a pre-signed URL, then references the
9
- * upload ID in the test trigger request.
4
+ * Mints an upload record and a presigned PUT URL + ephemeral X25519 public key
5
+ * for the overlay tarball. The developer encrypts the tarball with the returned
6
+ * public key and PUTs it directly to the object store; a test trigger then
7
+ * references the upload id. This is invoked by the Platform-first
8
+ * `test.relay.uploads.init` relay handler the developer never reaches the
9
+ * orchestrator's HTTP API directly.
10
10
  */
11
- import { Hono } from 'hono';
12
- import type { AppConfig } from '../config.js';
13
- import type { TokenManager } from '../secrets/token-manager.js';
14
11
  import type { Kysely } from 'kysely';
15
12
  import type { Database } from '../db/types.js';
16
13
  import type { CacheStorage } from '../storage/types.js';
17
- /**
18
- * Dependencies for upload routes.
19
- */
20
- export interface UploadRouteDeps {
21
- config: AppConfig;
14
+ /** Parameters for {@link initTestUpload}. */
15
+ export interface InitTestUploadParams {
16
+ routingKey: string;
17
+ sha?: string;
18
+ fileCount?: number;
19
+ compressedSize?: number;
20
+ /** PAT/actor identity that owns this upload, written to `test_uploads.created_by`. */
21
+ createdBy?: string | null;
22
+ /**
23
+ * When true, presign with the host-facing internal endpoint. When false (the
24
+ * Platform-relayed path), presign with the external/dev-reachable endpoint so
25
+ * a developer on a different network can PUT directly to the object store.
26
+ */
27
+ internal?: boolean;
28
+ }
29
+ /** Result of {@link initTestUpload}. */
30
+ export interface InitTestUploadResult {
31
+ uploadId: string;
32
+ signedUrl: string;
33
+ publicKey: string;
34
+ expiresIn: number;
35
+ }
36
+ /** Dependencies for {@link initTestUpload}. */
37
+ export interface InitTestUploadDeps {
22
38
  db: Kysely<Database>;
23
- tokenManager?: TokenManager;
24
39
  cacheStorage?: CacheStorage;
25
40
  }
26
- /** Hono env type for upload routes with context variables. */
27
- type UploadEnv = {
28
- Variables: {
29
- userId: string;
30
- routingKey: string | null;
31
- };
32
- };
33
41
  /**
34
- * Create Hono routes for upload management endpoints.
42
+ * Mint an upload record and return a presigned PUT URL + ephemeral X25519
43
+ * public key. The encryption keypair is generated per upload; the private key
44
+ * is stored orchestrator-side for post-PUT decryption. The `internal` flag
45
+ * selects the host-facing vs the external/dev-reachable presign endpoint.
35
46
  */
36
- export declare function createUploadRoutes(deps: UploadRouteDeps): Hono<UploadEnv>;
37
- export {};
47
+ export declare function initTestUpload(deps: InitTestUploadDeps, params: InitTestUploadParams): Promise<InitTestUploadResult>;
38
48
  //# sourceMappingURL=uploads.d.ts.map