@kici-dev/orchestrator 0.1.26 → 0.2.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.
- package/dist/__test-helpers__/mock-db.d.ts +2 -0
- package/dist/agent/dispatcher.d.ts +52 -2
- package/dist/agent/host-roster-reaper.d.ts +1 -2
- package/dist/agent/host-roster.d.ts +34 -0
- package/dist/agent/ownership-refusal.d.ts +12 -0
- package/dist/agent/ownership-tracker.d.ts +64 -16
- package/dist/agent/token-store.d.ts +13 -0
- package/dist/agent-packaging/availability.d.ts +27 -0
- package/dist/agent-packaging/build-package.d.ts +16 -0
- package/dist/agent-packaging/download.d.ts +30 -0
- package/dist/agent-packaging/index.d.ts +9 -0
- package/dist/agent-packaging/install-closure.d.ts +30 -0
- package/dist/agent-packaging/node-binary.d.ts +26 -0
- package/dist/agent-packaging/refresh.d.ts +50 -0
- package/dist/agent-packaging/store.d.ts +15 -0
- package/dist/agent-packaging/upload.d.ts +24 -0
- package/dist/app-on-error.d.ts +29 -0
- package/dist/app.d.ts +69 -8
- package/dist/approvals/apply-decision.d.ts +1 -1
- package/dist/approvals/step-approval-bridge.d.ts +1 -1
- package/dist/artifacts/artifact-store.d.ts +233 -0
- package/dist/artifacts/failure-messages.d.ts +46 -0
- package/dist/audit/access-log.d.ts +18 -1
- package/dist/cache/dep-cache.d.ts +15 -0
- package/dist/cache/pending-inits.d.ts +4 -4
- package/dist/cache/user-cache.d.ts +37 -0
- package/dist/cancel/cancel-run.d.ts +10 -3
- package/dist/cancel/dashboard-cancel-handler.d.ts +19 -0
- package/dist/cli/api-client.d.ts +51 -5
- package/dist/cli/commands/agent-package.d.ts +34 -0
- package/dist/cli/commands/check-run.d.ts +26 -0
- package/dist/cli/commands/cluster-settings.d.ts +55 -0
- package/dist/cli/commands/context.d.ts +25 -0
- package/dist/cli/commands/dashboard-encryption-key.d.ts +3 -0
- package/dist/cli/commands/db-backup.d.ts +71 -0
- package/dist/cli/commands/debug-bundle.d.ts +1 -1
- package/dist/cli/commands/orchestrator-service/drain.d.ts +31 -0
- package/dist/cli/commands/orchestrator-service/index.d.ts +7 -4
- package/dist/cli/commands/orchestrator-service/install-env.d.ts +58 -0
- package/dist/cli/commands/secret.d.ts +45 -1
- package/dist/cli/commands/shared/admin-cli-access-log.d.ts +46 -0
- package/dist/cli/commands/shared/versioned-upgrade.d.ts +65 -2
- package/dist/cli/commands/signing-key.d.ts +3 -0
- package/dist/cli/commands/source.d.ts +12 -0
- package/dist/cli/commands/token.d.ts +9 -0
- package/dist/cli/commands/trust-policy.d.ts +48 -0
- package/dist/cli/commands/variable.d.ts +6 -6
- package/dist/cli/join.d.ts +1 -1
- package/dist/cli/service/index.d.ts +2 -2
- package/dist/cli/service/instance/manifest.d.ts +17 -0
- package/dist/cli/service/instance/resolve.d.ts +11 -0
- package/dist/cli/service/windows.d.ts +6 -0
- package/dist/cli/wizard/orchestrator-wizard.d.ts +39 -11
- package/dist/cli.js +10263 -3667
- package/dist/cluster/cluster-settings-reader.d.ts +78 -0
- package/dist/cluster/coordinator.d.ts +81 -9
- package/dist/cluster/join-client.d.ts +1 -1
- package/dist/cluster/leader-gated-scheduler.d.ts +50 -0
- package/dist/cluster/orphan-recovery.d.ts +14 -0
- package/dist/cluster/peer-client.d.ts +12 -2
- package/dist/cluster/peer-handler.d.ts +15 -4
- package/dist/cluster/peer-registry.d.ts +12 -0
- package/dist/cluster/verified-issuer-poller.d.ts +11 -0
- package/dist/cluster/verified-issuer.d.ts +63 -0
- package/dist/cold-store/tables/access-log.d.ts +1 -1
- package/dist/cold-store/tables/event-log.d.ts +1 -1
- package/dist/cold-store/tables/execution-jobs.d.ts +1 -1
- package/dist/cold-store/tables/execution-runs.d.ts +1 -1
- package/dist/cold-store/tables/execution-steps.d.ts +1 -1
- package/dist/cold-store/tables/secret-audit-log.d.ts +1 -1
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/resolver.d.ts +2 -1
- package/dist/config/schema.d.ts +8 -6
- package/dist/config/types.d.ts +3 -2
- package/dist/config.d.ts +372 -46
- package/dist/contexts/binding-store.d.ts +36 -0
- package/dist/contexts/context-store.d.ts +100 -0
- package/dist/contexts/glob-specificity.d.ts +30 -0
- package/dist/{environments → contexts}/held-runs.d.ts +64 -32
- package/dist/{environments → contexts}/index.d.ts +1 -1
- package/dist/contexts/protection/aggregate.d.ts +43 -0
- package/dist/contexts/protection/branch-gate.d.ts +5 -0
- package/dist/contexts/protection/concurrency-gate.d.ts +4 -0
- package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
- package/dist/contexts/protection/reviewer-gate.d.ts +4 -0
- package/dist/{environments → contexts}/protection/satisfiability.d.ts +22 -22
- package/dist/contexts/protection/trust-gate.d.ts +4 -0
- package/dist/contexts/protection/wait-timer-gate.d.ts +4 -0
- package/dist/contexts/variable-store.d.ts +39 -0
- package/dist/cron/cron-scheduler.d.ts +24 -4
- package/dist/cron/cron-store.d.ts +21 -7
- package/dist/dashboard/attestation-filters.d.ts +94 -74
- package/dist/dashboard/handler.d.ts +63 -3
- package/dist/db/migration-test-harness.d.ts +41 -0
- package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
- package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
- package/dist/db/migrations/069_reroute_tunables.d.ts +21 -0
- package/dist/db/migrations/070_execution_runs_failure_class.d.ts +4 -0
- package/dist/db/migrations/071_batch_accumulation.d.ts +26 -0
- package/dist/db/migrations/072_dispatch_queue_run_id_index.d.ts +15 -0
- package/dist/db/migrations/073_org_settings_ingest_concurrency.d.ts +13 -0
- package/dist/db/migrations/074_normalize_zero_concurrency_limit.d.ts +13 -0
- package/dist/db/migrations/075_ingest_overflow_buffer.d.ts +16 -0
- package/dist/db/migrations/076_artifacts.d.ts +19 -0
- package/dist/db/migrations/077_backup_runs.d.ts +13 -0
- package/dist/db/migrations/078_org_settings_backup_staleness.d.ts +12 -0
- package/dist/db/migrations/079_org_settings_scaler_spawn_timeout.d.ts +14 -0
- package/dist/db/migrations/080_cluster_settings.d.ts +17 -0
- package/dist/db/migrations/081_org_settings_queue_timeout.d.ts +19 -0
- package/dist/db/migrations/082_host_s3_reachable.d.ts +16 -0
- package/dist/db/migrations/083_org_settings_artifact_caps.d.ts +18 -0
- package/dist/db/migrations/084_orchestrator_signing_keys.d.ts +20 -0
- package/dist/db/migrations/085_cluster_settings_reroute_flap_grace_ms.d.ts +12 -0
- package/dist/db/migrations/086_cluster_settings_max_fanout_hosts.d.ts +12 -0
- package/dist/db/migrations/087_cluster_settings_event_router_rate_limit.d.ts +12 -0
- package/dist/db/migrations/088_cluster_settings_cache_max_tarball_bytes.d.ts +12 -0
- package/dist/db/migrations/089_cluster_settings_cache_ttl_days.d.ts +12 -0
- package/dist/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.d.ts +12 -0
- package/dist/db/migrations/091_cluster_settings_agent_token_ttl_ms.d.ts +12 -0
- package/dist/db/migrations/092_cluster_settings_version.d.ts +16 -0
- package/dist/db/migrations/093_org_settings_sandbox_allowlist.d.ts +4 -0
- package/dist/db/migrations/094_dashboard_encryption_keys.d.ts +21 -0
- package/dist/db/migrations/095_dashboard_write_policy_tristate.d.ts +20 -0
- package/dist/db/migrations/096_multi_schedule_cron_last_fired.d.ts +4 -0
- package/dist/db/migrations/097_execution_runs_pr_number.d.ts +4 -0
- package/dist/db/migrations/098_execution_runs_customer_id.d.ts +4 -0
- package/dist/db/migrations/099_cluster_settings_dashboard_verified_issuer.d.ts +21 -0
- package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +31 -0
- package/dist/db/migrations/101_contexts_hold_expiry_drop_default.d.ts +31 -0
- package/dist/db/migrations/102_dispatch_queue_agent_id.d.ts +20 -0
- package/dist/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.d.ts +20 -0
- package/dist/db/migrations/104_check_run_terminal_sent.d.ts +22 -0
- package/dist/db/migrations/105_org_trust_policy.d.ts +19 -0
- package/dist/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.d.ts +18 -0
- package/dist/db/migrations/107_check_run_tracking_updated_at_index.d.ts +23 -0
- package/dist/db/repos/dashboard-encryption-keys-repo.d.ts +48 -0
- package/dist/db/repos/signing-keys-repo.d.ts +34 -0
- package/dist/db/types.d.ts +499 -66
- package/dist/deployment/deployment-identity.d.ts +87 -2
- package/dist/diagnostics/checks/backup.d.ts +18 -0
- package/dist/diagnostics/checks/index.d.ts +2 -1
- package/dist/diagnostics/fleet-collector.d.ts +1 -1
- package/dist/drain/drain-controller.d.ts +52 -0
- package/dist/events/batch-accumulator.d.ts +63 -0
- package/dist/events/circuit-breaker.d.ts +9 -3
- package/dist/events/event-emitter.d.ts +31 -0
- package/dist/events/event-retry-scanner.d.ts +12 -2
- package/dist/events/event-router.d.ts +29 -0
- package/dist/firecracker/host-network.d.ts +2 -0
- package/dist/firecracker/net-interfaces.d.ts +14 -0
- package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +19 -9
- package/dist/index.d.ts +2 -0
- package/dist/index.js +625 -22
- package/dist/lockfile-cache.d.ts +4 -0
- package/dist/lockfile-validate.d.ts +16 -9
- package/dist/metrics/prometheus.d.ts +114 -15
- package/dist/oidc/aws-kms-signer.d.ts +37 -0
- package/dist/oidc/command-signer.d.ts +23 -0
- package/dist/oidc/db-signer.d.ts +48 -0
- package/dist/oidc/id-token-claims.d.ts +76 -0
- package/dist/oidc/jwt.d.ts +18 -0
- package/dist/oidc/local-dev-signer.d.ts +31 -0
- package/dist/oidc/local-mint.d.ts +77 -0
- package/dist/oidc/oidc-mint-registration.d.ts +65 -0
- package/dist/oidc/orchestrator-mint.d.ts +97 -0
- package/dist/oidc/orchestrator-signer-factory.d.ts +33 -0
- package/dist/oidc/reconcile-signing-key.d.ts +21 -0
- package/dist/oidc/signer.d.ts +25 -0
- package/dist/oidc/signing-key-status.d.ts +23 -0
- package/dist/orchestrator-core.d.ts +42 -2
- package/dist/pipeline/decorating-secret-resolver.d.ts +5 -4
- package/dist/pipeline/dispatch-matched-workflow.d.ts +44 -3
- package/dist/pipeline/inline-eval.d.ts +2 -2
- package/dist/pipeline/install-secrets-resolver.d.ts +25 -14
- package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
- package/dist/pipeline/manual-schedule.d.ts +28 -14
- package/dist/pipeline/pending-workflow-context.d.ts +1 -1
- package/dist/pipeline/process-webhook.d.ts +57 -2
- package/dist/pipeline/processor.d.ts +49 -13
- package/dist/pipeline/request-idempotency.d.ts +28 -0
- package/dist/pipeline/rerun.d.ts +20 -13
- package/dist/pipeline/resolve-sandbox-grant.d.ts +28 -0
- package/dist/pipeline/resume-workflow.d.ts +1 -1
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +71 -0
- package/dist/pipeline/sandbox-allowlist-reader.d.ts +33 -0
- package/dist/pipeline/test-pipeline.d.ts +2 -2
- package/dist/policy/dashboard-write-policy.d.ts +9 -4
- package/dist/provenance/backfill-run.d.ts +1 -0
- package/dist/provenance/trust-root.d.ts +20 -0
- package/dist/provider-registry.d.ts +8 -0
- package/dist/providers/generic/normalizer.d.ts +1 -1
- package/dist/providers/github/auth.d.ts +1 -1
- package/dist/providers/github/changed-files.d.ts +14 -6
- package/dist/providers/github/check-status-poster.d.ts +19 -3
- package/dist/providers/github/contributor-resolver.d.ts +1 -1
- package/dist/providers/github/lock-file.d.ts +1 -1
- package/dist/providers/github/normalizer.d.ts +1 -1
- package/dist/providers/github/repo-url.d.ts +1 -1
- package/dist/providers/local/index.d.ts +1 -0
- package/dist/providers/local/local-source-config.d.ts +1 -0
- package/dist/providers/local/lock-file-fetcher.d.ts +1 -1
- package/dist/providers/local/normalizer.d.ts +1 -1
- package/dist/providers/local/repo-url-builder.d.ts +1 -1
- package/dist/providers/universal-git/changed-files.d.ts +8 -7
- package/dist/providers/universal-git/clone-token.d.ts +1 -1
- package/dist/providers/universal-git/config.d.ts +4 -4
- package/dist/providers/universal-git/index.d.ts +5 -1
- package/dist/providers/universal-git/lock-file.d.ts +6 -1
- package/dist/providers/universal-git/normalizer.d.ts +1 -1
- package/dist/providers/universal-git/repo-url.d.ts +1 -1
- package/dist/queue/cleanup.d.ts +69 -8
- package/dist/queue/job-queue.d.ts +94 -14
- package/dist/queue/scheduled-job.d.ts +2 -2
- package/dist/registration/registration-index.d.ts +1 -1
- package/dist/reporting/agent-failure-category.d.ts +4 -1
- package/dist/reporting/check-run-reporter.d.ts +34 -14
- package/dist/reporting/check-run-tracking-store.d.ts +70 -8
- package/dist/reporting/execution-tracker.d.ts +173 -17
- package/dist/reporting/fs-log-storage.d.ts +31 -2
- package/dist/reporting/job-check-run-completion.d.ts +50 -0
- package/dist/reporting/log-chunk-sink.d.ts +47 -0
- package/dist/reporting/log-retention.d.ts +16 -0
- package/dist/reporting/log-storage.d.ts +64 -4
- package/dist/reporting/log-writer.d.ts +22 -7
- package/dist/reporting/peer-log-normalize.d.ts +14 -0
- package/dist/reporting/run-aggregator.d.ts +36 -36
- package/dist/reporting/s3-log-storage.d.ts +102 -8
- package/dist/routes/admin-auth.d.ts +90 -0
- package/dist/routes/admin-cluster-settings.d.ts +31 -0
- package/dist/routes/admin-contexts.d.ts +47 -0
- package/dist/routes/admin-events.d.ts +3 -0
- package/dist/routes/admin-orchestrator-drain.d.ts +35 -0
- package/dist/routes/admin-registrations.d.ts +2 -2
- package/dist/routes/admin-runs.d.ts +9 -0
- package/dist/routes/admin-sources.d.ts +7 -0
- package/dist/routes/admin-trust-policy.d.ts +49 -0
- package/dist/routes/admin.d.ts +15 -1
- package/dist/routes/github-webhook.d.ts +9 -3
- package/dist/routes/provenance-oidc.d.ts +38 -0
- package/dist/routes/verify-attestation.d.ts +21 -0
- package/dist/scaler/bare-metal-backend.d.ts +9 -2
- package/dist/scaler/config.d.ts +25 -4
- package/dist/scaler/container-backend.d.ts +9 -1
- package/dist/scaler/firecracker-backend.d.ts +29 -2
- package/dist/scaler/index.d.ts +1 -1
- package/dist/scaler/manager.d.ts +166 -8
- package/dist/scaler/pending-scale-sweeper.d.ts +35 -0
- package/dist/scaler/types.d.ts +75 -6
- package/dist/secrets/backend-registry.d.ts +32 -1
- package/dist/secrets/context-secret-resolver.d.ts +30 -0
- package/dist/secrets/dashboard-encryption-key.d.ts +48 -0
- package/dist/secrets/ephemeral-keys.d.ts +16 -0
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/pg-secret-store.d.ts +13 -3
- package/dist/secrets/rbac.d.ts +5 -1
- package/dist/secrets/routing-key-scope.d.ts +6 -0
- package/dist/secrets/scope-routing.d.ts +126 -0
- package/dist/secrets/secret-resolver.d.ts +19 -32
- package/dist/secrets/token-manager.d.ts +5 -1
- package/dist/security/comment-handler.d.ts +1 -1
- package/dist/security/contributor-cache.d.ts +9 -1
- package/dist/security/trust-policy-gate.d.ts +117 -0
- package/dist/security/trust-policy-store.d.ts +78 -0
- package/dist/server.js +44012 -32721
- package/dist/sources/source-manager.d.ts +24 -0
- package/dist/stale-detector/stale-run-detector.d.ts +8 -1
- package/dist/standalone.js +44106 -33690
- package/dist/storage/blob-routes.d.ts +16 -0
- package/dist/storage/filesystem.d.ts +17 -0
- package/dist/storage/key-discriminator.d.ts +20 -0
- package/dist/storage/s3.d.ts +2 -0
- package/dist/storage/types.d.ts +16 -0
- package/dist/webhook/dedup.d.ts +9 -1
- package/dist/webhook/event-log.d.ts +13 -2
- package/dist/webhook/generic-sources-listener.d.ts +4 -0
- package/dist/webhook/ingest-admission.d.ts +140 -0
- package/dist/webhook/ingest-overflow-buffer.d.ts +27 -0
- package/dist/webhook/ingest-overflow-replayer.d.ts +49 -0
- package/dist/webhook/ingest-overflow-types.d.ts +73 -0
- package/dist/webhook/loop-lag-source.d.ts +40 -0
- package/dist/webhook/observed-relay-guard.d.ts +40 -0
- package/dist/webhook/org-ingest-cap-reader.d.ts +24 -0
- package/dist/webhook/register-source-bundle.d.ts +3 -0
- package/dist/webhook/relay-reinject.d.ts +43 -0
- package/dist/worker/in-memory-job-queue.d.ts +8 -3
- package/dist/worker-core.d.ts +10 -0
- package/dist/ws/agent-api-registry.d.ts +20 -0
- package/dist/ws/agent-handler.d.ts +63 -7
- package/dist/ws/bringup-api.d.ts +99 -0
- package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +43 -25
- package/dist/ws/dashboard-run-state-handler.d.ts +31 -0
- package/dist/ws/failure-messages.d.ts +29 -0
- package/dist/ws/oidc-token-relay.d.ts +15 -0
- package/dist/ws/ownership-gate.d.ts +22 -0
- package/dist/ws/platform-client.d.ts +96 -1
- package/dist/ws/replay-chunker.d.ts +37 -0
- package/installer-image-digests.json +3 -3
- package/package.json +22 -21
- package/sbom.spdx.json +1245 -1793
- package/dist/cli/commands/environment.d.ts +0 -25
- package/dist/environments/binding-store.d.ts +0 -36
- package/dist/environments/environment-store.d.ts +0 -87
- package/dist/environments/protection/aggregate.d.ts +0 -43
- package/dist/environments/protection/branch-gate.d.ts +0 -5
- package/dist/environments/protection/concurrency-gate.d.ts +0 -7
- package/dist/environments/protection/reviewer-gate.d.ts +0 -7
- package/dist/environments/protection/trust-gate.d.ts +0 -7
- package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
- package/dist/environments/variable-store.d.ts +0 -39
- package/dist/routes/admin-environments.d.ts +0 -47
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
* access is denied, or `null` to let the handler continue. The middleware
|
|
18
18
|
* mounted in each admin route file is responsible for calling
|
|
19
19
|
* `c.set('routingKey', tokenInfo.routingKey)` so these helpers can read it.
|
|
20
|
+
*
|
|
21
|
+
* NOT a scope name. `requested` must be a routing key (`<provider>:<id>`) read
|
|
22
|
+
* from a row or an explicit request field. Secret scope names live in a
|
|
23
|
+
* different namespace — a path whose `:` is reserved as the backend qualifier —
|
|
24
|
+
* and must never be passed here. Secret routes have no per-routing-key slice;
|
|
25
|
+
* they use `requireUnscopedToken` instead.
|
|
20
26
|
*/
|
|
21
27
|
import type { Context } from 'hono';
|
|
22
28
|
/**
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend-qualified scope routing.
|
|
3
|
+
*
|
|
4
|
+
* A secret scope travels over the wire in *qualified* form -- `<backend>:<path>`
|
|
5
|
+
* -- while every `SecretStore` implementation is addressed with the bare
|
|
6
|
+
* `<path>`. This module owns the single split between the two forms so the two
|
|
7
|
+
* write planes (the dashboard WebSocket handler and the HTTP admin API) can
|
|
8
|
+
* never drift apart on where the qualifier is stripped.
|
|
9
|
+
*
|
|
10
|
+
* The registered-backend map IS the whitelist: a head before the first `:` is a
|
|
11
|
+
* backend qualifier only when it names a registered backend. Anything else --
|
|
12
|
+
* an unregistered head, a leading `:`, no `:` at all -- stays whole and is
|
|
13
|
+
* routed to the default store, where the ordinary scope-name validation
|
|
14
|
+
* rejects it if it is malformed. That is what keeps routing keys
|
|
15
|
+
* (`<provider>:<id>`) out of the secret-scope namespace: `github:42` names no
|
|
16
|
+
* backend, so it stays whole and is rejected as a scope path.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The subset of `SecretStore` a scope-taking route or WS handler needs.
|
|
20
|
+
*
|
|
21
|
+
* Deliberately narrower than the full `SecretStore` from `@kici-dev/engine`:
|
|
22
|
+
* routing only needs the scope-addressed methods, so a caller may pass a
|
|
23
|
+
* partial store (the degraded store below, a unit-test fake) without
|
|
24
|
+
* implementing value resolution.
|
|
25
|
+
*/
|
|
26
|
+
export interface ScopedSecretStore {
|
|
27
|
+
listScopes(orgId: string): Promise<string[]>;
|
|
28
|
+
listKeys(orgId: string, scope: string): Promise<string[]>;
|
|
29
|
+
setSecret(orgId: string, scope: string, key: string, value: string): Promise<void>;
|
|
30
|
+
deleteSecret(orgId: string, scope: string, key: string): Promise<void>;
|
|
31
|
+
createScope?(orgId: string, scope: string): Promise<void>;
|
|
32
|
+
renameScope?(orgId: string, oldScope: string, newScope: string): Promise<void>;
|
|
33
|
+
deleteScope?(orgId: string, scope: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Raised when a secret write is issued against an orchestrator that has no
|
|
37
|
+
* secret store configured.
|
|
38
|
+
*
|
|
39
|
+
* The message is operator-facing: the dashboard write planes relay it verbatim
|
|
40
|
+
* as the `error` on their response, so it names the deployment condition rather
|
|
41
|
+
* than the internal cause.
|
|
42
|
+
*/
|
|
43
|
+
export declare class SecretsUnavailableError extends Error {
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The store an orchestrator serves the dashboard from when it has no secret
|
|
48
|
+
* store configured.
|
|
49
|
+
*
|
|
50
|
+
* The read/write asymmetry is deliberate. `listScopes` / `listKeys` return
|
|
51
|
+
* empty because "this deployment holds no secrets" is true and complete.
|
|
52
|
+
* `setSecret` / `deleteSecret` reject, because a write that resolved here would
|
|
53
|
+
* be discarded while the dashboard reported the secret as stored -- and a
|
|
54
|
+
* delete that resolved would leave a credential the operator believes is
|
|
55
|
+
* revoked. The optional scope methods stay unimplemented: the write planes
|
|
56
|
+
* already refuse a scope operation a store does not support.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createUnavailableSecretStore(): ScopedSecretStore;
|
|
59
|
+
/** Backend name assumed when a wire scope carries no recognised qualifier. */
|
|
60
|
+
export declare const DEFAULT_BACKEND_NAME = "pg";
|
|
61
|
+
/** Outcome of resolving a wire-form scope against the registered backends. */
|
|
62
|
+
export interface ResolvedScope<S> {
|
|
63
|
+
/** The store the operation must be issued against. */
|
|
64
|
+
store: S;
|
|
65
|
+
/** The backend the scope resolved to (the default name when unqualified). */
|
|
66
|
+
backendName: string;
|
|
67
|
+
/** The bare scope path to pass to the store -- never carries a qualifier. */
|
|
68
|
+
path: string;
|
|
69
|
+
/** True when the wire scope carried a recognised `<backend>:` qualifier. */
|
|
70
|
+
qualified: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The one method of the secret-backend registry that store loading needs.
|
|
74
|
+
*
|
|
75
|
+
* Structural on purpose: keeping the concrete registry out of this module lets
|
|
76
|
+
* both write planes -- and their unit tests -- supply their own loader without
|
|
77
|
+
* dragging a database-backed registry into a pure routing module.
|
|
78
|
+
*/
|
|
79
|
+
export interface BackendStoreRegistry<S, L> {
|
|
80
|
+
loadAllStores(auditLogger: L): Promise<Map<string, S>>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Load the registered secret backends for one operation.
|
|
84
|
+
*
|
|
85
|
+
* Never cache the result: a backend's credentials can rotate, and a backend can
|
|
86
|
+
* be added or removed, between operations -- a stale store would write to the
|
|
87
|
+
* wrong place. A registry failure propagates rather than degrading to the
|
|
88
|
+
* default store, because a misrouted secret write is worse than a failed one.
|
|
89
|
+
*
|
|
90
|
+
* The default-backend entry is ALWAYS `defaultStore`, overriding whatever the
|
|
91
|
+
* registry returned. The registry builds its own `PgSecretStore` for the seeded
|
|
92
|
+
* `pg` row, and that instance carries none of the orchestrator's configuration:
|
|
93
|
+
* `customerSecretsEnabled` defaults to true (so it would ignore an operator's
|
|
94
|
+
* `pgCustomerSecrets: false`), its key version is hardcoded to 1, and it has no
|
|
95
|
+
* old-master-key fallback (so it cannot decrypt rows written before a
|
|
96
|
+
* rotation). Overriding only when the registry omitted the entry is dead code
|
|
97
|
+
* -- the default row is seeded at startup -- and would let `pg:<path>` and
|
|
98
|
+
* `<path>` behave differently, which is the very defect this routing exists to
|
|
99
|
+
* fix.
|
|
100
|
+
*
|
|
101
|
+
* @param registry - Backend registry, or undefined when none is configured.
|
|
102
|
+
* @param auditLogger - Audit logger handed to the registry's store factory.
|
|
103
|
+
* @param defaultStore - Configured store for the default backend.
|
|
104
|
+
* @param defaultBackendName - Name the default store is registered under.
|
|
105
|
+
*/
|
|
106
|
+
export declare function loadRoutableStores<S, L>(registry: BackendStoreRegistry<S, L> | undefined, auditLogger: L, defaultStore: S, defaultBackendName?: string): Promise<Map<string, S>>;
|
|
107
|
+
/**
|
|
108
|
+
* Split a wire-form scope into the store that owns it and the bare path.
|
|
109
|
+
*
|
|
110
|
+
* Pure: takes the already-loaded store map rather than loading it, so both
|
|
111
|
+
* planes can unit-test routing without a database.
|
|
112
|
+
*
|
|
113
|
+
* @param wireScope - Scope as supplied by the caller, possibly `<backend>:<path>`.
|
|
114
|
+
* @param stores - Registered backends, keyed by backend name.
|
|
115
|
+
* @param defaultStore - Store used when the scope carries no recognised qualifier.
|
|
116
|
+
* @param defaultBackendName - Backend name reported for an unqualified scope.
|
|
117
|
+
*/
|
|
118
|
+
export declare function resolveScope<S>(wireScope: string, stores: Map<string, S>, defaultStore: S, defaultBackendName?: string): ResolvedScope<S>;
|
|
119
|
+
/**
|
|
120
|
+
* Join a backend name and a bare path back into wire form.
|
|
121
|
+
*
|
|
122
|
+
* Used for audit records and cross-backend listings, so an operator reading the
|
|
123
|
+
* audit log sees the same qualified string the caller sent.
|
|
124
|
+
*/
|
|
125
|
+
export declare function toWireScope(backendName: string, path: string): string;
|
|
126
|
+
//# sourceMappingURL=scope-routing.d.ts.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Secret resolver for dispatch-time secret resolution.
|
|
3
3
|
*
|
|
4
|
-
* Uses
|
|
5
|
-
* When a job dispatches with
|
|
6
|
-
* 1. Looks up the
|
|
7
|
-
* 2. Gets bindings for that
|
|
4
|
+
* Uses context bindings + scope resolver to match secrets from multiple backends.
|
|
5
|
+
* When a job dispatches with a context name, the resolver:
|
|
6
|
+
* 1. Looks up the context by name
|
|
7
|
+
* 2. Gets bindings for that context
|
|
8
8
|
* 3. Queries ALL registered backend stores for secrets
|
|
9
9
|
* 4. Prefixes each secret's scope with the backend name (e.g., pg:aws/prod)
|
|
10
|
-
* 5. Uses
|
|
10
|
+
* 5. Uses resolveSecretsWithProvenance to match bindings against prefixed secrets
|
|
11
11
|
* 6. Returns a flat decrypted key-value map
|
|
12
12
|
*
|
|
13
13
|
* unreachable backends cause job failure (not silent skip).
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
* longest-path-wins uses scope path after stripping backend prefix.
|
|
16
16
|
* audit log includes backend name.
|
|
17
17
|
*/
|
|
18
|
-
import { type
|
|
18
|
+
import { type ContextBinding, type HostFacts, type ScopedSecret } from '@kici-dev/engine';
|
|
19
19
|
import type { Logger } from '@kici-dev/shared';
|
|
20
20
|
import type { AuditLogger } from './audit-logger.js';
|
|
21
21
|
/**
|
|
22
|
-
* Minimal
|
|
22
|
+
* Minimal context store interface (subset needed by resolver).
|
|
23
23
|
*/
|
|
24
|
-
export interface
|
|
24
|
+
export interface ContextStoreLike {
|
|
25
25
|
getByName(orgId: string, name: string): Promise<{
|
|
26
26
|
id: string;
|
|
27
27
|
name: string;
|
|
@@ -32,7 +32,7 @@ export interface EnvironmentStoreLike {
|
|
|
32
32
|
* Minimal binding store interface (subset needed by resolver).
|
|
33
33
|
*/
|
|
34
34
|
export interface BindingStoreLike {
|
|
35
|
-
|
|
35
|
+
getByContextId(contextId: string): Promise<ContextBinding[]>;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Minimal secret store interface (subset needed by resolver).
|
|
@@ -49,7 +49,7 @@ export interface SecretStoreLike {
|
|
|
49
49
|
* Dependencies for the SecretResolver.
|
|
50
50
|
*/
|
|
51
51
|
export interface SecretResolverDeps {
|
|
52
|
-
|
|
52
|
+
contextStore: ContextStoreLike;
|
|
53
53
|
bindingStore: BindingStoreLike;
|
|
54
54
|
/** Map of backend name to store. Replaces single secretStore. */
|
|
55
55
|
backendStores: Map<string, SecretStoreLike>;
|
|
@@ -69,16 +69,16 @@ export interface ResolvedSecretMeta {
|
|
|
69
69
|
* can flow through `ProcessingDeps.secretResolver`.
|
|
70
70
|
*/
|
|
71
71
|
export interface SecretResolverApi {
|
|
72
|
-
resolveForJob(orgId: string,
|
|
72
|
+
resolveForJob(orgId: string, contextName: string, hostCtx?: HostFacts): Promise<Record<string, string>>;
|
|
73
73
|
resolveNamed(orgId: string, scope: string, key: string, opts?: {
|
|
74
74
|
store?: string;
|
|
75
75
|
runId?: string;
|
|
76
76
|
jobId?: string;
|
|
77
77
|
}): Promise<string | null>;
|
|
78
|
-
resolveForJobWithMeta(orgId: string,
|
|
78
|
+
resolveForJobWithMeta(orgId: string, contextName: string, hostCtx?: HostFacts): Promise<Record<string, ResolvedSecretMeta>>;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* Resolves secrets for a job by matching
|
|
81
|
+
* Resolves secrets for a job by matching context bindings against scoped secrets
|
|
82
82
|
* from multiple backends.
|
|
83
83
|
*
|
|
84
84
|
* All backend stores are queried. Each secret's scope is prefixed with the backend
|
|
@@ -87,7 +87,7 @@ export interface SecretResolverApi {
|
|
|
87
87
|
* stripping the backend prefix.
|
|
88
88
|
*/
|
|
89
89
|
export declare class SecretResolver implements SecretResolverApi {
|
|
90
|
-
private readonly
|
|
90
|
+
private readonly contextStore;
|
|
91
91
|
private readonly bindingStore;
|
|
92
92
|
private readonly backendStores;
|
|
93
93
|
private readonly auditLogger;
|
|
@@ -97,17 +97,17 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
97
97
|
* Resolve secrets for a job dispatch.
|
|
98
98
|
*
|
|
99
99
|
* @param orgId - Organization ID
|
|
100
|
-
* @param
|
|
100
|
+
* @param contextName - Context name to resolve secrets for
|
|
101
101
|
* @param hostCtx - Optional fan-out child identity for per-host resolution.
|
|
102
102
|
* When supplied, each binding is gated by its `host_pattern` and its
|
|
103
103
|
* `scope_pattern` is templated per-child; when omitted, only fleet-wide
|
|
104
104
|
* (`'**'`) non-templated bindings contribute.
|
|
105
105
|
* @returns Flat map of decrypted secret key-value pairs
|
|
106
106
|
*/
|
|
107
|
-
resolveForJob(orgId: string,
|
|
107
|
+
resolveForJob(orgId: string, contextName: string, hostCtx?: HostFacts): Promise<Record<string, string>>;
|
|
108
108
|
/**
|
|
109
109
|
* Resolve a single named secret by (orgId, scope, key), optionally scoped to
|
|
110
|
-
* a specific backend. Bypasses
|
|
110
|
+
* a specific backend. Bypasses context bindings — this is a direct
|
|
111
111
|
* lookup used for source-scoped credentials (e.g. universal-git PAT/SSH
|
|
112
112
|
* keys stored under `__source__/<sourceId>`).
|
|
113
113
|
*
|
|
@@ -130,7 +130,7 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
130
130
|
*
|
|
131
131
|
* Returns the secret value along with which backend and scope provided it.
|
|
132
132
|
*/
|
|
133
|
-
resolveForJobWithMeta(orgId: string,
|
|
133
|
+
resolveForJobWithMeta(orgId: string, contextName: string, hostCtx?: HostFacts): Promise<Record<string, ResolvedSecretMeta>>;
|
|
134
134
|
/**
|
|
135
135
|
* Collect all secrets from all backend stores, prefixing scopes.
|
|
136
136
|
* Per /: unreachable backends are tracked but not fatal here.
|
|
@@ -142,24 +142,11 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
142
142
|
*/
|
|
143
143
|
private buildDecryptFn;
|
|
144
144
|
/**
|
|
145
|
-
* Check if any failed backend could affect the job's
|
|
145
|
+
* Check if any failed backend could affect the job's context bindings.
|
|
146
146
|
* throw when a failed backend's scopes could match a binding and
|
|
147
147
|
* no healthy backend already satisfies that binding.
|
|
148
148
|
* jobs referencing only healthy backends succeed normally.
|
|
149
149
|
*/
|
|
150
150
|
private checkScopedFailure;
|
|
151
|
-
/**
|
|
152
|
-
* Find the winning secret for a given key, mirroring the engine scope
|
|
153
|
-
* resolver's host-aware matching and `(host specificity, scope depth)`
|
|
154
|
-
* precedence so the enriched metadata reports the same secret the flat
|
|
155
|
-
* resolution selected.
|
|
156
|
-
*/
|
|
157
|
-
private findWinningSecret;
|
|
158
|
-
/**
|
|
159
|
-
* Resolve the effective scope pattern a binding contributes for a host,
|
|
160
|
-
* applying the host gate and per-child scope templating. Mirrors the engine
|
|
161
|
-
* scope resolver's `bindingScopeForHost`. Returns `null` to skip the binding.
|
|
162
|
-
*/
|
|
163
|
-
private bindingScopeForHost;
|
|
164
151
|
}
|
|
165
152
|
//# sourceMappingURL=secret-resolver.d.ts.map
|
|
@@ -16,15 +16,19 @@ export declare class TokenManager {
|
|
|
16
16
|
* @param label - Human-readable label for this token.
|
|
17
17
|
* @param role - Role to assign (owner, admin, auditor).
|
|
18
18
|
* @param routingKey - Optional routing key scope (null = all).
|
|
19
|
+
* @param expiresAt - Optional absolute expiry. When omitted the token
|
|
20
|
+
* never expires (null); `validate()` already enforces the column.
|
|
19
21
|
* @returns The plaintext token (shown once) and the row ID.
|
|
20
22
|
*/
|
|
21
|
-
generateToken(label: string, role: Role, routingKey?: string | null): Promise<{
|
|
23
|
+
generateToken(label: string, role: Role, routingKey?: string | null, expiresAt?: Date | null): Promise<{
|
|
22
24
|
token: string;
|
|
23
25
|
id: string;
|
|
24
26
|
}>;
|
|
25
27
|
/**
|
|
26
28
|
* Validate a plaintext token against stored hashes.
|
|
27
29
|
*
|
|
30
|
+
* On success, fires a non-blocking update to last_used_at.
|
|
31
|
+
*
|
|
28
32
|
* @param token - The plaintext token to validate.
|
|
29
33
|
* @returns Token info if valid, null if invalid/expired/revoked.
|
|
30
34
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* approval/rejection of security holds. Verifies commenter identity
|
|
6
6
|
* via the trust policy cache and checks ci_trust:write+ before acting.
|
|
7
7
|
*/
|
|
8
|
-
import type { HeldRunStore } from '../
|
|
8
|
+
import type { HeldRunStore } from '../contexts/held-runs.js';
|
|
9
9
|
import { type IdentityLink, type PermissionLevel } from './trust-resolver.js';
|
|
10
10
|
import type { CheckStatusPoster as EngineCheckStatusPoster } from '@kici-dev/engine';
|
|
11
11
|
/** Parsed /kici command from a comment body. */
|
|
@@ -5,18 +5,26 @@
|
|
|
5
5
|
* Uses a 15-minute TTL and 10,000 max entries.
|
|
6
6
|
*/
|
|
7
7
|
import type { ContributorResolver, ContributorInfo } from '@kici-dev/engine';
|
|
8
|
+
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
8
9
|
/**
|
|
9
10
|
* Caches ContributorResolver results in an LRU cache.
|
|
10
11
|
*
|
|
11
12
|
* Cache key format: `{provider}:{repoFullName}:{username}`
|
|
12
|
-
* TTL:
|
|
13
|
+
* TTL: cluster-configurable (`cluster_settings.contributor_cache_ttl_ms`,
|
|
14
|
+
* default 15 minutes). The TTL is resolved at each `set()` and applied
|
|
15
|
+
* per-entry, so a live override affects newly-cached entries without a restart.
|
|
13
16
|
*/
|
|
14
17
|
export declare class ContributorCache {
|
|
15
18
|
private readonly cache;
|
|
19
|
+
private readonly clusterSettings?;
|
|
20
|
+
private readonly defaultTtlMs;
|
|
16
21
|
constructor(options?: {
|
|
17
22
|
ttlMs?: number;
|
|
18
23
|
maxEntries?: number;
|
|
24
|
+
clusterSettings?: ClusterSettingsReader;
|
|
19
25
|
});
|
|
26
|
+
/** Resolve the fleet-wide contributor-cache TTL (ms), falling back to the config default. */
|
|
27
|
+
private ttlMs;
|
|
20
28
|
/**
|
|
21
29
|
* Build the cache key from provider, repo, and username.
|
|
22
30
|
*/
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Org trust-policy gate — turns the Platform-owned policy plus three per-PR
|
|
3
|
+
* signals into exactly one outcome.
|
|
4
|
+
*
|
|
5
|
+
* Pure: no I/O, no DB, no clock. The caller supplies the effective policy (see
|
|
6
|
+
* `resolveEffectivePolicy`) and the signals; enforcement lives in the dispatch
|
|
7
|
+
* gate.
|
|
8
|
+
*
|
|
9
|
+
* Scope: the caller only invokes this for sources whose provider bundle carries
|
|
10
|
+
* a `ContributorResolver` (GitHub today). Every other source is trusted by
|
|
11
|
+
* construction and never reaches here.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import type { OrchestratorMode, TrustPolicy, TrustTier } from '@kici-dev/engine';
|
|
15
|
+
import { SecurityHoldReason } from '../contexts/held-runs.js';
|
|
16
|
+
import type { StoredTrustPolicy } from './trust-policy-store.js';
|
|
17
|
+
/**
|
|
18
|
+
* Which arm of the gate is actually in force for an org — the vocabulary the
|
|
19
|
+
* admin API reports and `kici-admin trust-policy show` renders.
|
|
20
|
+
*
|
|
21
|
+
* `policy` means `resolveEffectivePolicy` produced a policy and all three arms
|
|
22
|
+
* apply; `legacy` means it produced `null`, so only the legacy
|
|
23
|
+
* workflow-modification rule runs and there are no policy values to report.
|
|
24
|
+
* Named here, next to the resolver that decides between them, so the route and
|
|
25
|
+
* the CLI cannot drift apart on a bare string literal.
|
|
26
|
+
*/
|
|
27
|
+
export declare const TrustPolicyEnforcement: z.ZodEnum<{
|
|
28
|
+
legacy: "legacy";
|
|
29
|
+
policy: "policy";
|
|
30
|
+
}>;
|
|
31
|
+
export type TrustPolicyEnforcement = z.infer<typeof TrustPolicyEnforcement>;
|
|
32
|
+
/** The per-PR facts the policy is evaluated against. */
|
|
33
|
+
export interface TrustPolicySignals {
|
|
34
|
+
/** Resolved contributor tier; undefined when trust resolution failed. */
|
|
35
|
+
tier: TrustTier | undefined;
|
|
36
|
+
/** The PR's head repo differs from its base repo. */
|
|
37
|
+
isForkPR: boolean;
|
|
38
|
+
/** The PR changes `.kici/` workflow definitions. */
|
|
39
|
+
hasWorkflowModifications: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The reasons the ORG TRUST POLICY itself can raise — its three arms.
|
|
43
|
+
*
|
|
44
|
+
* `context_trust` is excluded at the type level rather than merely by
|
|
45
|
+
* convention: that reason belongs to the per-context minimum-trust gate, which
|
|
46
|
+
* holds an individual job under its real name. Narrowing here is what lets
|
|
47
|
+
* `SECURITY_HOLD_JOB_IDS` drop its phantom `context_trust` sentinel — a value
|
|
48
|
+
* that existed only to satisfy a `Record<SecurityHoldReason, ...>` and was never
|
|
49
|
+
* written to a single row.
|
|
50
|
+
*/
|
|
51
|
+
export type TrustPolicyHoldReason = Exclude<SecurityHoldReason, 'context_trust'>;
|
|
52
|
+
export type TrustPolicyOutcome = {
|
|
53
|
+
action: 'pass';
|
|
54
|
+
} | {
|
|
55
|
+
action: 'hold';
|
|
56
|
+
reason: TrustPolicyHoldReason;
|
|
57
|
+
message: string;
|
|
58
|
+
/**
|
|
59
|
+
* Hours the resulting hold stays approvable, taken from the SAME policy
|
|
60
|
+
* that produced this verdict. `null` in independent mode, where there is
|
|
61
|
+
* no upstream policy and therefore no operator-set window.
|
|
62
|
+
*
|
|
63
|
+
* Carried on the outcome rather than re-read at the hold site: a second,
|
|
64
|
+
* independent read bypassed `resolveEffectivePolicy`, so it was both a
|
|
65
|
+
* TOCTOU (the policy could change between deciding and sizing) and a
|
|
66
|
+
* divergence — independent mode got the 72h default where the decision
|
|
67
|
+
* path deliberately has no policy at all.
|
|
68
|
+
*/
|
|
69
|
+
approvalExpiryHours: number | null;
|
|
70
|
+
} | {
|
|
71
|
+
action: 'reject';
|
|
72
|
+
reason: TrustPolicyHoldReason;
|
|
73
|
+
message: string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The policy a Platform-attached orchestrator applies when it has no stored
|
|
77
|
+
* row. Every arm holds — a hold is recoverable by approval, and these are the
|
|
78
|
+
* documented org defaults, so an org that never changed its policy gets the
|
|
79
|
+
* behavior its dashboard shows.
|
|
80
|
+
*
|
|
81
|
+
* This is NOT necessarily a brief transient. The Platform sends
|
|
82
|
+
* `trust_policy.update` only when the org has a `trust_policies` row, and that
|
|
83
|
+
* row is created lazily on a dashboard read — so an org that has never opened
|
|
84
|
+
* Settings > CI trust receives no push at all and stays on these values
|
|
85
|
+
* indefinitely. The expiry is therefore the generous documented default rather
|
|
86
|
+
* than a short one: a short window would auto-fail legitimate runs.
|
|
87
|
+
*/
|
|
88
|
+
export declare const FAIL_CLOSED_POLICY: TrustPolicy;
|
|
89
|
+
/**
|
|
90
|
+
* Pick the policy to evaluate. A stored row always wins. Without one, a
|
|
91
|
+
* Platform-attached orchestrator fails closed (a push is imminent); an
|
|
92
|
+
* independent orchestrator has no upstream authority at all, so it gets `null`
|
|
93
|
+
* and the evaluator applies only the legacy rule — which is what keeps this
|
|
94
|
+
* change from silently gating existing independent deployments on upgrade.
|
|
95
|
+
*
|
|
96
|
+
* `PLATFORM_CONNECTED_MODES` is the shared definition of "expects a Platform
|
|
97
|
+
* push", so a mode added there is fail-closed here without a second edit.
|
|
98
|
+
*/
|
|
99
|
+
export declare function resolveEffectivePolicy(stored: StoredTrustPolicy | null, mode: OrchestratorMode): TrustPolicy | null;
|
|
100
|
+
/**
|
|
101
|
+
* Evaluate the policy.
|
|
102
|
+
*
|
|
103
|
+
* Arms are evaluated in a fixed order — workflow_modification, fork_pr,
|
|
104
|
+
* unknown_contributor — and then any `reject` beats any `hold`, with the first
|
|
105
|
+
* arm in that order supplying the reason among equals. That makes a PR tripping
|
|
106
|
+
* several arms produce one outcome with a stable reason rather than a verdict
|
|
107
|
+
* that depends on evaluation accident.
|
|
108
|
+
*
|
|
109
|
+
* An unresolved tier (`undefined`) counts as `unknown`, never as a pass: a
|
|
110
|
+
* trust resolution that could not be answered is not evidence of trust.
|
|
111
|
+
*
|
|
112
|
+
* A `null` policy applies only the legacy rule (workflow modifications by a
|
|
113
|
+
* non-trusted contributor hold), reproducing behavior from before the policy was
|
|
114
|
+
* enforced.
|
|
115
|
+
*/
|
|
116
|
+
export declare function evaluateTrustPolicy(policy: TrustPolicy | null, signals: TrustPolicySignals): TrustPolicyOutcome;
|
|
117
|
+
//# sourceMappingURL=trust-policy-gate.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache of the Platform-owned org trust policy.
|
|
3
|
+
*
|
|
4
|
+
* The Platform is the authority for a Platform-attached org and pushes the
|
|
5
|
+
* policy on `trust_policy.update`; this store persists it so the policy survives
|
|
6
|
+
* a restart instead of being unknown until the next push. In independent mode
|
|
7
|
+
* there is no Platform, so the operator writes the same row via
|
|
8
|
+
* `kici-admin trust-policy set` and `source` records which wrote it.
|
|
9
|
+
*/
|
|
10
|
+
import { Kysely, type Transaction } from 'kysely';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import type { TrustPolicy } from '@kici-dev/engine';
|
|
13
|
+
import type { Database } from '../db/types.js';
|
|
14
|
+
/** Who wrote the cached policy row. */
|
|
15
|
+
export declare const TrustPolicySource: z.ZodEnum<{
|
|
16
|
+
local: "local";
|
|
17
|
+
platform: "platform";
|
|
18
|
+
}>;
|
|
19
|
+
export type TrustPolicySource = z.infer<typeof TrustPolicySource>;
|
|
20
|
+
/**
|
|
21
|
+
* The strictest documented defaults. Used to fill gaps on a local merge; the
|
|
22
|
+
* fail-closed policy an unknown org resolves to lives in `trust-policy-gate.ts`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_TRUST_POLICY: TrustPolicy;
|
|
25
|
+
/** A policy as stored, with its provenance. */
|
|
26
|
+
export interface StoredTrustPolicy extends TrustPolicy {
|
|
27
|
+
source: TrustPolicySource;
|
|
28
|
+
updatedAt: Date;
|
|
29
|
+
}
|
|
30
|
+
export declare class TrustPolicyStore {
|
|
31
|
+
private readonly db;
|
|
32
|
+
constructor(db: Kysely<Database>);
|
|
33
|
+
/** `executor` lets a caller read inside its own transaction. */
|
|
34
|
+
get(orgId: string, executor?: Kysely<Database> | Transaction<Database>): Promise<StoredTrustPolicy | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Needs no lock, unlike `upsertLocal`: a push carries every field, so there
|
|
37
|
+
* is no read-merge to lose and concurrent pushes correctly settle on the
|
|
38
|
+
* last one. The two writers also never overlap — `upsertLocal` is reachable
|
|
39
|
+
* only in independent mode, where no Platform pushes.
|
|
40
|
+
*/
|
|
41
|
+
upsertFromPlatform(orgId: string, policy: TrustPolicy): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Write an operator-supplied policy. Only reachable in independent mode — the
|
|
44
|
+
* admin route refuses on a Platform-attached orchestrator, because the next
|
|
45
|
+
* push would clobber the write.
|
|
46
|
+
*
|
|
47
|
+
* The read-merge-write is serialised per org by a transaction-scoped
|
|
48
|
+
* advisory lock. The transaction alone would NOT give that: under READ
|
|
49
|
+
* COMMITTED two concurrent PATCHes both read the pre-existing row, and the
|
|
50
|
+
* second `ON CONFLICT DO UPDATE` then overwrites every column from its own
|
|
51
|
+
* stale merge — silently dropping the first operator's change (a tightened
|
|
52
|
+
* `unknownContributorPolicy` reverting to whatever the second caller last
|
|
53
|
+
* saw). The lock releases on commit or rollback, so there is no unlock to
|
|
54
|
+
* leak.
|
|
55
|
+
*
|
|
56
|
+
* `onWrite` receives the same transaction and the merged result, so an audit
|
|
57
|
+
* row written there commits or rolls back with the policy itself — a
|
|
58
|
+
* loosened `forkPolicy` can never land unattributed.
|
|
59
|
+
*
|
|
60
|
+
* Returns the merged policy so the caller does not need a second read (which
|
|
61
|
+
* would be outside the transaction and could observe a later write).
|
|
62
|
+
*/
|
|
63
|
+
upsertLocal(orgId: string, patch: Partial<TrustPolicy>, onWrite?: (trx: Transaction<Database>, merged: TrustPolicy) => Promise<void>): Promise<TrustPolicy>;
|
|
64
|
+
private write;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build a TrustPolicyStore backed by its own connection pool to the given
|
|
68
|
+
* orchestrator database URL. Mirrors `createHeldRunStoreFromUrl`; consumed by
|
|
69
|
+
* E2E tests that assert the pushed policy is persisted in the real deployed
|
|
70
|
+
* orchestrator DB rather than held in process memory.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createTrustPolicyStoreFromUrl(databaseUrl: string, opts?: {
|
|
73
|
+
maxConnections?: number;
|
|
74
|
+
}): {
|
|
75
|
+
store: TrustPolicyStore;
|
|
76
|
+
dispose: () => Promise<void>;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=trust-policy-store.d.ts.map
|