@kici-dev/orchestrator 0.1.27 → 0.3.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 +56 -4
- 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/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 +44 -1
- 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/dashboard-encryption-key.d.ts +3 -0
- package/dist/cli/commands/db-backup.d.ts +71 -0
- 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/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/wizard/orchestrator-wizard.d.ts +39 -11
- package/dist/cli.js +9921 -3409
- 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 +9 -6
- package/dist/config/types.d.ts +5 -2
- package/dist/config.d.ts +366 -53
- package/dist/contexts/context-store.d.ts +21 -8
- package/dist/contexts/glob-specificity.d.ts +30 -0
- package/dist/contexts/held-runs.d.ts +51 -19
- package/dist/contexts/protection/aggregate.d.ts +2 -2
- package/dist/contexts/protection/concurrency-gate.d.ts +0 -3
- package/dist/contexts/protection/reviewer-gate.d.ts +0 -3
- package/dist/contexts/protection/satisfiability.d.ts +1 -1
- package/dist/contexts/protection/trust-gate.d.ts +0 -3
- package/dist/contexts/protection/wait-timer-gate.d.ts +0 -3
- 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 +92 -74
- package/dist/dashboard/handler.d.ts +35 -1
- package/dist/db/migration-test-harness.d.ts +41 -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/migrations/108_unroutable_fast_fail.d.ts +4 -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 +441 -7
- 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 +18 -8
- package/dist/index.d.ts +2 -0
- package/dist/index.js +654 -29
- package/dist/lockfile-cache.d.ts +4 -0
- package/dist/lockfile-validate.d.ts +16 -9
- package/dist/metrics/prometheus.d.ts +113 -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 +22 -9
- package/dist/oidc/jwt.d.ts +5 -2
- package/dist/oidc/local-dev-signer.d.ts +1 -1
- package/dist/oidc/oidc-mint-registration.d.ts +27 -11
- 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 +3 -2
- package/dist/pipeline/dispatch-matched-workflow.d.ts +41 -0
- package/dist/pipeline/install-secrets-resolver.d.ts +12 -1
- package/dist/pipeline/manual-schedule.d.ts +20 -13
- 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 +44 -8
- package/dist/pipeline/rerun.d.ts +12 -13
- package/dist/pipeline/resolve-sandbox-grant.d.ts +28 -0
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +71 -0
- package/dist/pipeline/sandbox-allowlist-reader.d.ts +33 -0
- 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 +13 -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/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/bootstrap.d.ts +5 -0
- package/dist/queue/cleanup.d.ts +72 -9
- package/dist/queue/job-queue.d.ts +141 -14
- package/dist/queue/scheduled-job.d.ts +3 -2
- package/dist/queue/terminalize-unroutable.d.ts +53 -0
- package/dist/queue/unroutable-probe.d.ts +52 -0
- 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 +156 -10
- 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 +50 -33
- 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-events.d.ts +3 -0
- package/dist/routes/admin-orchestrator-drain.d.ts +35 -0
- 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/dashboard-encryption-key.d.ts +48 -0
- package/dist/secrets/ephemeral-keys.d.ts +16 -0
- package/dist/secrets/pg-secret-store.d.ts +10 -0
- 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 +1 -14
- package/dist/secrets/token-manager.d.ts +5 -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 +36074 -25052
- package/dist/sources/source-manager.d.ts +24 -0
- package/dist/stale-detector/stale-run-detector.d.ts +7 -0
- package/dist/standalone.js +35203 -25387
- 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-context-handler.d.ts +28 -10
- 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 +9 -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 +1240 -1788
|
@@ -51,11 +51,28 @@ export declare class FilesystemCacheStorage implements CacheStorage {
|
|
|
51
51
|
delete(key: string): Promise<boolean>;
|
|
52
52
|
touch(key: string): Promise<void>;
|
|
53
53
|
getUrl(key: string, ttlMsOverride?: number): Promise<string | null>;
|
|
54
|
+
presignedGetTtlSeconds(): number;
|
|
54
55
|
getUploadUrl(key: string): Promise<string>;
|
|
55
56
|
getInternalUploadUrl(key: string): Promise<string>;
|
|
56
57
|
initMeta(key: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* List cache keys under a prefix.
|
|
60
|
+
*
|
|
61
|
+
* The prefix is a **key prefix**, not necessarily a directory — `UserCache`'s
|
|
62
|
+
* `restoreKeys` fallback lists on `${prefix}${seg(restoreKey)}`, a partial
|
|
63
|
+
* object name. Two shapes, and both must work the way the S3 backend does:
|
|
64
|
+
*
|
|
65
|
+
* - trailing `/` — a directory. Walk it directly; this is the hot path.
|
|
66
|
+
* - no trailing `/` — a partial name. Walk the parent directory and filter by
|
|
67
|
+
* the prefix, since the prefix itself may name a file (or nothing at all).
|
|
68
|
+
*
|
|
69
|
+
* Reading the prefix as a directory in the second case is what made the
|
|
70
|
+
* `restoreKeys` fallback silently never hit here (`ENOENT` → `[]`) or throw
|
|
71
|
+
* (`ENOTDIR`, when a real object carried that exact name).
|
|
72
|
+
*/
|
|
57
73
|
list(subPrefix: string): Promise<string[]>;
|
|
58
74
|
getMetadata(key: string): Promise<CacheMetadata | null>;
|
|
75
|
+
getObjectSize(key: string): Promise<number | null>;
|
|
59
76
|
copy(srcKey: string, destKey: string): Promise<void>;
|
|
60
77
|
/**
|
|
61
78
|
* Recursively collect data files under `dir`, returning each as a cache key
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Width of the object-key discriminator, in hex characters.
|
|
3
|
+
*
|
|
4
|
+
* 32 hex chars is 128 bits, and the width is a security property rather than a
|
|
5
|
+
* formatting choice: on a case-insensitive namespace the discriminator is the
|
|
6
|
+
* only thing separating object names chosen by untrusted workflow code. A
|
|
7
|
+
* narrower value would let that code search case variants for a colliding pair
|
|
8
|
+
* and land two different payloads on one object.
|
|
9
|
+
*/
|
|
10
|
+
export declare const KEY_DISCRIMINATOR_LENGTH = 32;
|
|
11
|
+
/**
|
|
12
|
+
* A collision-resistant discriminator for a user-supplied object-key segment.
|
|
13
|
+
*
|
|
14
|
+
* Hashes the **exact** name, before any sanitization. Sanitizing is many-to-one
|
|
15
|
+
* — `seg()` maps both `/` and `_` to `_`, so `a/b` and `a_b` collapse to one
|
|
16
|
+
* segment — and a case-insensitive backend folds `build` onto `Build`. Hashing
|
|
17
|
+
* the pre-sanitization name is what keeps each of those pairs two objects.
|
|
18
|
+
*/
|
|
19
|
+
export declare function keyDiscriminator(exact: string): string;
|
|
20
|
+
//# sourceMappingURL=key-discriminator.d.ts.map
|
package/dist/storage/s3.d.ts
CHANGED
|
@@ -70,11 +70,13 @@ export declare class S3CacheStorage implements CacheStorage {
|
|
|
70
70
|
delete(key: string): Promise<boolean>;
|
|
71
71
|
touch(key: string): Promise<void>;
|
|
72
72
|
getUrl(key: string, ttlMsOverride?: number): Promise<string | null>;
|
|
73
|
+
presignedGetTtlSeconds(): number;
|
|
73
74
|
getUploadUrl(key: string): Promise<string>;
|
|
74
75
|
getInternalUploadUrl(key: string): Promise<string>;
|
|
75
76
|
initMeta(key: string): Promise<void>;
|
|
76
77
|
list(subPrefix: string): Promise<string[]>;
|
|
77
78
|
getMetadata(key: string): Promise<CacheMetadata | null>;
|
|
79
|
+
getObjectSize(key: string): Promise<number | null>;
|
|
78
80
|
copy(srcKey: string, destKey: string): Promise<void>;
|
|
79
81
|
/** Delete an S3 object. Idempotent (doesn't error if missing). */
|
|
80
82
|
private deleteObject;
|
package/dist/storage/types.d.ts
CHANGED
|
@@ -51,6 +51,15 @@ export interface CacheStorage {
|
|
|
51
51
|
* `ttlMsOverride` applies a per-operation TTL (see `get`).
|
|
52
52
|
*/
|
|
53
53
|
getUrl(key: string, ttlMsOverride?: number): Promise<string | null>;
|
|
54
|
+
/**
|
|
55
|
+
* The validity window, in seconds, of the pre-signed download URLs this
|
|
56
|
+
* backend mints via `getUrl` — i.e. how long after minting a `getUrl` link
|
|
57
|
+
* still authorizes a download before its signature expires. This is the
|
|
58
|
+
* signature expiry, NOT the artifact-retention TTL; consumers that render a
|
|
59
|
+
* `getUrl` link (e.g. the dashboard artifacts panel) use it to refresh the
|
|
60
|
+
* link before it stops working.
|
|
61
|
+
*/
|
|
62
|
+
presignedGetTtlSeconds(): number;
|
|
54
63
|
/**
|
|
55
64
|
* Generate a pre-signed PUT URL for direct agent upload.
|
|
56
65
|
* Uses the external endpoint (container-routable) when configured.
|
|
@@ -86,6 +95,13 @@ export interface CacheStorage {
|
|
|
86
95
|
* eviction to order candidates by access recency.
|
|
87
96
|
*/
|
|
88
97
|
getMetadata(key: string): Promise<CacheMetadata | null>;
|
|
98
|
+
/**
|
|
99
|
+
* Byte size of the stored object, or null when the object is missing. A pure
|
|
100
|
+
* stat — no metadata write and no TTL/last-accessed side effect. Used to
|
|
101
|
+
* verify an artifact's real size server-side instead of trusting the
|
|
102
|
+
* agent-declared value.
|
|
103
|
+
*/
|
|
104
|
+
getObjectSize(key: string): Promise<number | null>;
|
|
89
105
|
}
|
|
90
106
|
import type { SharedS3Config } from '@kici-dev/shared';
|
|
91
107
|
/**
|
package/dist/webhook/dedup.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely';
|
|
2
2
|
import type { Database } from '../db/types.js';
|
|
3
|
+
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
3
4
|
/**
|
|
4
5
|
* Delivery ID deduplication cache with dual-layer storage:
|
|
5
6
|
* 1. In-memory Set for hot-path performance (last 10,000 IDs)
|
|
@@ -12,7 +13,14 @@ export declare class DedupCache {
|
|
|
12
13
|
private readonly db;
|
|
13
14
|
private readonly memoryCache;
|
|
14
15
|
private readonly insertionOrder;
|
|
15
|
-
|
|
16
|
+
private readonly clusterSettings?;
|
|
17
|
+
private readonly defaultTtlMs;
|
|
18
|
+
constructor(db: Kysely<Database>, opts?: {
|
|
19
|
+
clusterSettings?: ClusterSettingsReader;
|
|
20
|
+
defaultTtlMs?: number;
|
|
21
|
+
});
|
|
22
|
+
/** Resolve the fleet-wide dedup TTL (ms), falling back to the config default. */
|
|
23
|
+
private ttlMs;
|
|
16
24
|
/**
|
|
17
25
|
* Check if a delivery ID has already been processed.
|
|
18
26
|
* Checks in-memory cache first (fast path), then DB.
|
|
@@ -2,11 +2,18 @@ import { EventLogStatus, EventLogSource } from '@kici-dev/engine';
|
|
|
2
2
|
import type { Kysely } from 'kysely';
|
|
3
3
|
import type { Database } from '../db/types.js';
|
|
4
4
|
import type { LogStorage } from '../reporting/log-storage.js';
|
|
5
|
+
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
5
6
|
import type { WebhookInfo } from './handler.js';
|
|
6
7
|
/** Configuration for the writer. */
|
|
7
8
|
export interface EventLogWriterOptions {
|
|
8
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Cluster-wide fallback soft cap in bytes for payload upload (default 5 MB),
|
|
11
|
+
* used when no live `cluster_settings.event_log_max_payload_bytes` override
|
|
12
|
+
* is set. Read per-write through {@link ClusterSettingsReader}.
|
|
13
|
+
*/
|
|
9
14
|
maxPayloadBytes: number;
|
|
15
|
+
/** Optional fleet-wide settings reader; when present overrides maxPayloadBytes per write. */
|
|
16
|
+
clusterSettings?: ClusterSettingsReader;
|
|
10
17
|
}
|
|
11
18
|
/**
|
|
12
19
|
* Outcome metadata recorded alongside the delivery row.
|
|
@@ -30,7 +37,11 @@ export interface EventLogOutcome {
|
|
|
30
37
|
ref?: string | null;
|
|
31
38
|
/** First run spawned by this delivery. */
|
|
32
39
|
runId?: string | null;
|
|
33
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Failure reason when status='failed', or a degraded-evaluation note on a
|
|
42
|
+
* status='processed' row (e.g. path filters matched conservatively against
|
|
43
|
+
* an unavailable changed-files diff). Free-text; not tied to a single status.
|
|
44
|
+
*/
|
|
34
45
|
errorMessage?: string | null;
|
|
35
46
|
}
|
|
36
47
|
/**
|
|
@@ -39,6 +39,7 @@ import type { GenericSourceManager } from './generic-sources.js';
|
|
|
39
39
|
import type { ProviderRegistry } from '../provider-registry.js';
|
|
40
40
|
import type { AppConfig } from '../config.js';
|
|
41
41
|
import type { SecretResolver } from '../secrets/secret-resolver.js';
|
|
42
|
+
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
42
43
|
export interface GenericSourcesChangeListenerOptions {
|
|
43
44
|
/** Raw pg pool — a dedicated PoolClient is checked out for LISTEN. */
|
|
44
45
|
pool: pg.Pool;
|
|
@@ -51,6 +52,9 @@ export interface GenericSourcesChangeListenerOptions {
|
|
|
51
52
|
/** Required for universal-git source rows; null is acceptable on
|
|
52
53
|
* peers that cannot serve them. */
|
|
53
54
|
secretResolver: SecretResolver | null;
|
|
55
|
+
/** Fleet-wide settings reader; threads the live lock-file cap into warm-path
|
|
56
|
+
* universal-git fetcher registration. */
|
|
57
|
+
clusterSettings?: ClusterSettingsReader;
|
|
54
58
|
/** Active scaler backend on this peer. Threaded into the warm-path
|
|
55
59
|
* registration so a local source added at runtime on a container /
|
|
56
60
|
* firecracker scaler emits the same reachability warning as a cold-boot one. */
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { LoopLagSource } from './loop-lag-source.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reasons a webhook-ingest admission is shed by the {@link IngestAdmissionController}.
|
|
5
|
+
*
|
|
6
|
+
* - `loop_overload` — the event-loop-lag gate is latched open (p99 delay above
|
|
7
|
+
* the shed threshold); admission sheds immediately, DB-free.
|
|
8
|
+
* - `codel_drop` — the CoDel controlled-delay queue is standing (minimum
|
|
9
|
+
* sojourn stayed above target for a full interval); the head is dropped.
|
|
10
|
+
* - `queue_full` — the bounded queue is at capacity, or the caller disallowed
|
|
11
|
+
* queueing (the WS relay path) and no slot was immediately available.
|
|
12
|
+
* - `max_sojourn` — a waiter exceeded the hard sojourn ceiling (< the Platform
|
|
13
|
+
* WS ack timeout) and is dropped so nothing waits past the caller's timeout.
|
|
14
|
+
*/
|
|
15
|
+
export declare const IngestShedReason: z.ZodEnum<{
|
|
16
|
+
codel_drop: "codel_drop";
|
|
17
|
+
loop_overload: "loop_overload";
|
|
18
|
+
max_sojourn: "max_sojourn";
|
|
19
|
+
queue_full: "queue_full";
|
|
20
|
+
}>;
|
|
21
|
+
export type IngestShedReason = z.infer<typeof IngestShedReason>;
|
|
22
|
+
export type AdmitResult = {
|
|
23
|
+
admitted: true;
|
|
24
|
+
release: () => void;
|
|
25
|
+
} | {
|
|
26
|
+
admitted: false;
|
|
27
|
+
reason: IngestShedReason;
|
|
28
|
+
};
|
|
29
|
+
/** Per-call admission options. */
|
|
30
|
+
export interface AdmitOptions {
|
|
31
|
+
/**
|
|
32
|
+
* When true (HTTP direct ingress), a request that cannot be admitted
|
|
33
|
+
* immediately is enqueued on the CoDel queue. When false (Platform-WS relay,
|
|
34
|
+
* whose ack the Platform awaits synchronously with a 5 s budget), no queueing
|
|
35
|
+
* happens — the request is granted immediately or shed `queue_full` at once.
|
|
36
|
+
*/
|
|
37
|
+
allowQueue?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface IngestAdmissionConfig {
|
|
40
|
+
maxConcurrency: number;
|
|
41
|
+
maxQueueDepth: number;
|
|
42
|
+
codelTargetMs: number;
|
|
43
|
+
codelIntervalMs: number;
|
|
44
|
+
queueMaxWaitMs: number;
|
|
45
|
+
loopLagShedMs: number;
|
|
46
|
+
loopLagResumeMs: number;
|
|
47
|
+
loopLagSampleMs: number;
|
|
48
|
+
}
|
|
49
|
+
export interface IngestAdmissionSnapshot {
|
|
50
|
+
inflight: number;
|
|
51
|
+
queueDepth: number;
|
|
52
|
+
sheddingActive: boolean;
|
|
53
|
+
loopDelayP99Ms: number;
|
|
54
|
+
loopDelayMaxMs: number;
|
|
55
|
+
}
|
|
56
|
+
export interface IngestAdmissionDeps {
|
|
57
|
+
config: IngestAdmissionConfig;
|
|
58
|
+
loopLag: LoopLagSource;
|
|
59
|
+
/** injectable clock (default Date.now). */
|
|
60
|
+
now?: () => number;
|
|
61
|
+
/** durable-buffer seam (default no-op) — a future replay buffer plugs in here. */
|
|
62
|
+
onShed?: (reason: IngestShedReason, key: string) => void;
|
|
63
|
+
/** metric hook: shed counter increment (keeps the controller OTel-free). */
|
|
64
|
+
onShedMetric?: (reason: IngestShedReason) => void;
|
|
65
|
+
/** metric hook: admitted counter increment. */
|
|
66
|
+
onAdmitMetric?: () => void;
|
|
67
|
+
/** metric hook: state gauges refresh. */
|
|
68
|
+
onStateChange?: (s: IngestAdmissionSnapshot) => void;
|
|
69
|
+
/** start the real sweep timer (default true; unit tests pass false and drive tickQueue/sampleLoopLag). */
|
|
70
|
+
startTimer?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Single-process admission controller for the webhook-ingest pipeline. Three
|
|
74
|
+
* layers evaluated in order on {@link admit}: (1) an event-loop-lag gate (the
|
|
75
|
+
* DB-free adaptive signal), (2) hard global + per-org caps (memory backstop +
|
|
76
|
+
* fairness), (3) a CoDel controlled-delay queue (burst absorption without
|
|
77
|
+
* bufferbloat). Shed is lossy — the caller redelivers.
|
|
78
|
+
*/
|
|
79
|
+
export declare class IngestAdmissionController {
|
|
80
|
+
private readonly cfg;
|
|
81
|
+
private readonly loopLag;
|
|
82
|
+
private readonly now;
|
|
83
|
+
private readonly onShedSeam;
|
|
84
|
+
private readonly onShedMetric?;
|
|
85
|
+
private readonly onAdmitMetric?;
|
|
86
|
+
private readonly onStateChange?;
|
|
87
|
+
private globalInflight;
|
|
88
|
+
private readonly perKeyInflight;
|
|
89
|
+
private readonly queue;
|
|
90
|
+
private loopP99;
|
|
91
|
+
private loopMax;
|
|
92
|
+
/** Hysteresis latch for the loop-lag gate (open = shedding). */
|
|
93
|
+
private loopGateOpen;
|
|
94
|
+
/** CoDel: timestamp the head sojourn first rose above target; undefined when below. */
|
|
95
|
+
private codelAboveSince;
|
|
96
|
+
private codelDropping;
|
|
97
|
+
private readonly sweepTimer;
|
|
98
|
+
private stopped;
|
|
99
|
+
constructor(deps: IngestAdmissionDeps);
|
|
100
|
+
private keyInflight;
|
|
101
|
+
private incKey;
|
|
102
|
+
private decKey;
|
|
103
|
+
isShedding(): boolean;
|
|
104
|
+
snapshot(): IngestAdmissionSnapshot;
|
|
105
|
+
private emit;
|
|
106
|
+
/**
|
|
107
|
+
* Sample the loop-lag source into the snapshot and update the hysteresis
|
|
108
|
+
* latch. Called on the sweep interval (production) or directly (tests).
|
|
109
|
+
*/
|
|
110
|
+
sampleLoopLag(): void;
|
|
111
|
+
private canAdmit;
|
|
112
|
+
private makeRelease;
|
|
113
|
+
private grant;
|
|
114
|
+
private shed;
|
|
115
|
+
/**
|
|
116
|
+
* @param key fairness key — org id (preferred) or routing key (DB-degraded fallback).
|
|
117
|
+
* @param orgCap per-key concurrency cap P (from the cached settings reader).
|
|
118
|
+
*/
|
|
119
|
+
admit(key: string, orgCap: number, opts?: AdmitOptions): Promise<AdmitResult>;
|
|
120
|
+
/**
|
|
121
|
+
* Drive the queue: admit admissible waiters (fair skip of maxed keys), sweep
|
|
122
|
+
* the hard sojourn ceiling, then evaluate CoDel on the head. Called on every
|
|
123
|
+
* release and on the sweep interval; also test-drivable with the injected clock.
|
|
124
|
+
*/
|
|
125
|
+
tickQueue(): void;
|
|
126
|
+
/** Release-driven fair dequeue: admit the first admissible waiter, skip maxed keys. */
|
|
127
|
+
private admitWaiters;
|
|
128
|
+
/** Hard sojourn ceiling: shed any waiter that waited past W_max. */
|
|
129
|
+
private sweepMaxSojourn;
|
|
130
|
+
/**
|
|
131
|
+
* CoDel head evaluation. While the head sojourn is below target, reset the
|
|
132
|
+
* dropping state (a transient burst drains cleanly). Once the head has stayed
|
|
133
|
+
* at/above target continuously for a full interval, enter the dropping state
|
|
134
|
+
* and shed the head each sweep until sojourn recovers below target.
|
|
135
|
+
*/
|
|
136
|
+
private codelEval;
|
|
137
|
+
/** Stop the sweep timer and drain the queue (every waiter resolves as shed). */
|
|
138
|
+
stop(): void;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=ingest-admission.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../db/types.js';
|
|
3
|
+
import { type OverflowDelivery } from './ingest-overflow-types.js';
|
|
4
|
+
export interface IngestOverflowBufferDeps {
|
|
5
|
+
db: Kysely<Database>;
|
|
6
|
+
/** Buffered-row cap (KICI_INGEST_OVERFLOW_MAX). */
|
|
7
|
+
maxRows: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Capture side of the durable overflow buffer. On a shed, the ingest path calls
|
|
11
|
+
* {@link IngestOverflowBuffer.capture} additively (the 429 still stands). At the
|
|
12
|
+
* row cap, capture drops the delivery from the buffer (never unbounded rows) —
|
|
13
|
+
* the lossy fallback a retrying sender still covers.
|
|
14
|
+
*/
|
|
15
|
+
export declare class IngestOverflowBuffer {
|
|
16
|
+
private readonly db;
|
|
17
|
+
private readonly maxRows;
|
|
18
|
+
constructor(deps: IngestOverflowBufferDeps);
|
|
19
|
+
/** Current buffered-row depth. */
|
|
20
|
+
currentDepth(): Promise<number>;
|
|
21
|
+
/**
|
|
22
|
+
* Persist a shed delivery. Returns true when a `buffered` row was inserted,
|
|
23
|
+
* false when the buffer is at cap (delivery dropped, `cap_full` metric bumped).
|
|
24
|
+
*/
|
|
25
|
+
capture(d: OverflowDelivery): Promise<boolean>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ingest-overflow-buffer.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../db/types.js';
|
|
3
|
+
import { WebhookIngestOutcome } from '../pipeline/process-webhook.js';
|
|
4
|
+
import { type OverflowDelivery } from './ingest-overflow-types.js';
|
|
5
|
+
export type ReinjectFn = (d: OverflowDelivery) => Promise<WebhookIngestOutcome>;
|
|
6
|
+
export interface IngestOverflowReplayerDeps {
|
|
7
|
+
db: Kysely<Database>;
|
|
8
|
+
controller: {
|
|
9
|
+
isShedding(): boolean;
|
|
10
|
+
};
|
|
11
|
+
intervalMs: number;
|
|
12
|
+
batchSize: number;
|
|
13
|
+
maxAttempts: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Background drain for the durable overflow buffer. A pass runs only while the
|
|
17
|
+
* admission controller is NOT shedding (replaying into a still-overloaded
|
|
18
|
+
* orchestrator just re-sheds), claims the oldest `buffered` rows FIFO up to a
|
|
19
|
+
* bounded batch, and re-injects each through the admission-gated ingest path.
|
|
20
|
+
* A re-shed or error reverts the row to `buffered` (never lost); past the
|
|
21
|
+
* max-attempts ceiling it goes `failed`. Successful rows are swept.
|
|
22
|
+
*/
|
|
23
|
+
export declare class IngestOverflowReplayer {
|
|
24
|
+
private readonly db;
|
|
25
|
+
private readonly controller;
|
|
26
|
+
private readonly intervalMs;
|
|
27
|
+
private readonly batchSize;
|
|
28
|
+
private readonly maxAttempts;
|
|
29
|
+
private reinjectDirect;
|
|
30
|
+
private reinjectRelay;
|
|
31
|
+
private timer;
|
|
32
|
+
private running;
|
|
33
|
+
private stopped;
|
|
34
|
+
constructor(deps: IngestOverflowReplayerDeps);
|
|
35
|
+
setReinjectDirect(fn: ReinjectFn): void;
|
|
36
|
+
setReinjectRelay(fn: ReinjectFn): void;
|
|
37
|
+
start(): void;
|
|
38
|
+
stop(): void;
|
|
39
|
+
/** One drain pass. Test-drivable. */
|
|
40
|
+
runPass(): Promise<void>;
|
|
41
|
+
/** Select the oldest buffered rows and claim each via a conditional update. */
|
|
42
|
+
private claimBatch;
|
|
43
|
+
private toDelivery;
|
|
44
|
+
private replayOne;
|
|
45
|
+
private revertOrFail;
|
|
46
|
+
private sweepReplayed;
|
|
47
|
+
private refreshDepthGauge;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=ingest-overflow-replayer.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { WebhookInfo } from './handler.js';
|
|
3
|
+
import type { RelayStartMeta } from './relay-buffer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle of a durably-buffered shed delivery.
|
|
6
|
+
*
|
|
7
|
+
* - `buffered` — captured, awaiting replay.
|
|
8
|
+
* - `replaying` — claimed by a replay pass (a conditional-update lock so a
|
|
9
|
+
* restart / second loop cannot double-claim the same row).
|
|
10
|
+
* - `replayed` — successfully re-injected through normal ingest; swept.
|
|
11
|
+
* - `failed` — re-shed / errored past the max-attempts ceiling; kept for
|
|
12
|
+
* operator inspection with `last_error`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const OverflowStatus: z.ZodEnum<{
|
|
15
|
+
buffered: "buffered";
|
|
16
|
+
failed: "failed";
|
|
17
|
+
replayed: "replayed";
|
|
18
|
+
replaying: "replaying";
|
|
19
|
+
}>;
|
|
20
|
+
export type OverflowStatus = z.infer<typeof OverflowStatus>;
|
|
21
|
+
/**
|
|
22
|
+
* Which ingest boundary captured the delivery, and therefore how it is replayed:
|
|
23
|
+
*
|
|
24
|
+
* - `direct` — HTTP direct-ingress. The delivery was already signature-verified
|
|
25
|
+
* and normalized at ingest; replay re-injects the stored `WebhookInfo` through
|
|
26
|
+
* the admission-gated HTTP path (no re-verification).
|
|
27
|
+
* - `relay` — Platform-WS relay. The delivery was shed BEFORE signature
|
|
28
|
+
* verification; replay MUST re-verify the raw body against the stored headers.
|
|
29
|
+
*/
|
|
30
|
+
export declare const OverflowSourceKind: z.ZodEnum<{
|
|
31
|
+
direct: "direct";
|
|
32
|
+
relay: "relay";
|
|
33
|
+
}>;
|
|
34
|
+
export type OverflowSourceKind = z.infer<typeof OverflowSourceKind>;
|
|
35
|
+
/** Reasons a delivery is permanently dropped from the overflow buffer. */
|
|
36
|
+
export declare const OverflowDropReason: z.ZodEnum<{
|
|
37
|
+
cap_full: "cap_full";
|
|
38
|
+
max_attempts: "max_attempts";
|
|
39
|
+
}>;
|
|
40
|
+
export type OverflowDropReason = z.infer<typeof OverflowDropReason>;
|
|
41
|
+
/** Verify-input envelope for a `relay`-origin delivery (mirrors RelayStartMeta). */
|
|
42
|
+
export interface OverflowRelayMeta {
|
|
43
|
+
signatureHeaderName: string | null;
|
|
44
|
+
signatureHeader: string | null;
|
|
45
|
+
clientIp: string | null;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
requestId?: string;
|
|
48
|
+
}
|
|
49
|
+
/** A delivery captured for durable overflow replay. */
|
|
50
|
+
export interface OverflowDelivery {
|
|
51
|
+
deliveryId: string;
|
|
52
|
+
routingKey: string;
|
|
53
|
+
sourceKind: OverflowSourceKind;
|
|
54
|
+
/** Provider type (direct: from WebhookInfo; relay: resolved at replay). */
|
|
55
|
+
provider: string | null;
|
|
56
|
+
event: string;
|
|
57
|
+
action: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Base64 of the raw delivery bytes. For `direct` this is the JSON-serialized
|
|
60
|
+
* payload; for `relay` it is the verbatim wire body (base64 preserves bytes so
|
|
61
|
+
* a non-JSON generic payload replays intact and HMAC re-verification matches).
|
|
62
|
+
*/
|
|
63
|
+
body: string;
|
|
64
|
+
/** Verify metadata; empty for `direct` (already verified). */
|
|
65
|
+
meta: OverflowRelayMeta;
|
|
66
|
+
}
|
|
67
|
+
/** Build a capture record from a verified HTTP-direct `WebhookInfo`. */
|
|
68
|
+
export declare function deliveryFromDirect(info: WebhookInfo): OverflowDelivery;
|
|
69
|
+
/** Build a capture record from a pre-verify WS relay `meta` + raw body. */
|
|
70
|
+
export declare function deliveryFromRelay(meta: RelayStartMeta, body: Buffer): OverflowDelivery;
|
|
71
|
+
/** Reconstruct a normalized `WebhookInfo` from a `direct`-origin delivery. */
|
|
72
|
+
export declare function overflowDeliveryToInfo(d: OverflowDelivery): WebhookInfo;
|
|
73
|
+
//# sourceMappingURL=ingest-overflow-types.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-loop delay source for the ingest admission controller's adaptive gate.
|
|
3
|
+
*
|
|
4
|
+
* The controller reads p99/max loop delay on a short interval to decide whether
|
|
5
|
+
* to shed. Hiding the real `perf_hooks` primitive behind this interface lets the
|
|
6
|
+
* gate decision logic and the real sampler be tested separately: the controller
|
|
7
|
+
* unit tests drive a {@link FakeLoopLagSource} with caller-controlled values, and
|
|
8
|
+
* {@link RealLoopLagSource} has its own busy-spin detection test.
|
|
9
|
+
*/
|
|
10
|
+
export interface LoopLagSource {
|
|
11
|
+
/** p99 event-loop delay in ms over the current window. */
|
|
12
|
+
p99(): number;
|
|
13
|
+
/** max event-loop delay in ms over the current window. */
|
|
14
|
+
max(): number;
|
|
15
|
+
/** reset the window's histogram (start a fresh measurement window). */
|
|
16
|
+
reset(): void;
|
|
17
|
+
/** stop the underlying monitor (real source only; no-op on the fake). */
|
|
18
|
+
stop(): void;
|
|
19
|
+
}
|
|
20
|
+
/** Real source backed by `perf_hooks.monitorEventLoopDelay`. */
|
|
21
|
+
export declare class RealLoopLagSource implements LoopLagSource {
|
|
22
|
+
private readonly h;
|
|
23
|
+
constructor(resolutionMs?: number);
|
|
24
|
+
p99(): number;
|
|
25
|
+
max(): number;
|
|
26
|
+
reset(): void;
|
|
27
|
+
stop(): void;
|
|
28
|
+
}
|
|
29
|
+
/** Deterministic test double returning caller-controlled p99/max values. */
|
|
30
|
+
export declare class FakeLoopLagSource implements LoopLagSource {
|
|
31
|
+
private _p99;
|
|
32
|
+
private _max;
|
|
33
|
+
setP99(v: number): void;
|
|
34
|
+
setMax(v: number): void;
|
|
35
|
+
p99(): number;
|
|
36
|
+
max(): number;
|
|
37
|
+
reset(): void;
|
|
38
|
+
stop(): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=loop-lag-source.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side half of the `observed`-mode "no relay, ever" guarantee.
|
|
3
|
+
*
|
|
4
|
+
* An `observed` orchestrator ingests only its OWN webhooks — providers post
|
|
5
|
+
* straight to its public URL and nothing transits the hosted Platform. The
|
|
6
|
+
* Platform never selects an observed connection as a relay target, so a relay
|
|
7
|
+
* reaching one is a defect somewhere upstream. These handlers make that case
|
|
8
|
+
* loud and inert instead of silently processing the payload.
|
|
9
|
+
*/
|
|
10
|
+
import { WebhookRelayResult } from '@kici-dev/engine';
|
|
11
|
+
/** Thrown when a Platform relay reaches an observed-mode orchestrator. */
|
|
12
|
+
export declare class ObservedRelayRefusedError extends Error {
|
|
13
|
+
constructor(routingKey: string);
|
|
14
|
+
}
|
|
15
|
+
/** Reason string returned on both the verify and the refusal paths. */
|
|
16
|
+
export declare const OBSERVED_RELAY_REFUSAL_REASON = "orchestrator is in observed mode and does not accept Platform-relayed webhooks";
|
|
17
|
+
/** Minimal logger surface the guard needs (keeps the module test-friendly). */
|
|
18
|
+
type WarnLogger = {
|
|
19
|
+
warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* `onVerifyInbound` for observed mode: refuse every relayed webhook at verify
|
|
23
|
+
* time, so the Platform gets a definitive `rejected_misconfigured` ack instead
|
|
24
|
+
* of a timeout.
|
|
25
|
+
*/
|
|
26
|
+
export declare function observedRelayVerify(): {
|
|
27
|
+
result: WebhookRelayResult;
|
|
28
|
+
reason: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* `onWebhookRelay` for observed mode: log loudly and reject so nothing is
|
|
32
|
+
* processed. Rejecting (rather than returning) keeps the failure visible in the
|
|
33
|
+
* Platform client's relay error path.
|
|
34
|
+
*/
|
|
35
|
+
export declare function observedRelayReject(logger: WarnLogger, meta: {
|
|
36
|
+
routingKey: string;
|
|
37
|
+
deliveryId?: string;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=observed-relay-guard.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../db/types.js';
|
|
3
|
+
/** The resolved fairness key + per-key concurrency cap for an ingest admission. */
|
|
4
|
+
export interface AdmissionKey {
|
|
5
|
+
key: string;
|
|
6
|
+
orgCap: number;
|
|
7
|
+
}
|
|
8
|
+
export interface OrgIngestCapReader {
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the fairness key + per-org cap for a routing key. Never throws; on a
|
|
11
|
+
* DB error / cold-miss-slow it degrades to `{ key: routingKey, orgCap:
|
|
12
|
+
* clusterDefault }` (per-routing-key fairness, DB-free) so admission never
|
|
13
|
+
* blocks on a sick DB.
|
|
14
|
+
*/
|
|
15
|
+
resolve(routingKey: string): Promise<AdmissionKey>;
|
|
16
|
+
}
|
|
17
|
+
export declare function createOrgIngestCapReader(deps: {
|
|
18
|
+
db?: Kysely<Database>;
|
|
19
|
+
clusterDefault: number;
|
|
20
|
+
orgTtlMs?: number;
|
|
21
|
+
capTtlMs?: number;
|
|
22
|
+
maxEntries?: number;
|
|
23
|
+
}): OrgIngestCapReader;
|
|
24
|
+
//# sourceMappingURL=org-ingest-cap-reader.d.ts.map
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
import type { AppConfig } from '../config.js';
|
|
34
34
|
import type { ProviderRegistry } from '../provider-registry.js';
|
|
35
35
|
import type { SecretResolver } from '../secrets/secret-resolver.js';
|
|
36
|
+
import type { ClusterSettingsReader } from '../cluster/cluster-settings-reader.js';
|
|
36
37
|
import type { GenericWebhookSource } from '../db/types.js';
|
|
37
38
|
export interface RegisterSourceBundleDeps {
|
|
38
39
|
providerRegistry: ProviderRegistry;
|
|
@@ -40,6 +41,8 @@ export interface RegisterSourceBundleDeps {
|
|
|
40
41
|
/** Required for universal-git source rows. Null is allowed; rows that
|
|
41
42
|
* carry `git_config` will be skipped with a metric bump. */
|
|
42
43
|
secretResolver: SecretResolver | null;
|
|
44
|
+
/** Fleet-wide settings reader; threads the live lock-file cap into universal-git fetchers. */
|
|
45
|
+
clusterSettings?: ClusterSettingsReader;
|
|
43
46
|
/** Active scaler backend on this peer. When 'container' or 'firecracker', a
|
|
44
47
|
* local source registration emits a one-time reachability warning (the repo
|
|
45
48
|
* must exist inside the agent filesystem, not just on the orchestrator host). */
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AdmitResult } from './ingest-admission.js';
|
|
2
|
+
import type { WebhookInfo } from './handler.js';
|
|
3
|
+
import { WebhookIngestOutcome } from '../pipeline/process-webhook.js';
|
|
4
|
+
import type { OverflowDelivery } from './ingest-overflow-types.js';
|
|
5
|
+
import type { ReinjectFn } from './ingest-overflow-replayer.js';
|
|
6
|
+
/** Verify outcome shape the reinject cares about (subset of VerifyOutcome). */
|
|
7
|
+
export interface RelayVerifyResult {
|
|
8
|
+
result: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Collaborator seams for {@link buildRelayReinject}. Injected so the reinject
|
|
12
|
+
* orchestration + payload parsing can be unit-tested without the DB / secret
|
|
13
|
+
* store / provider registry. server.ts wires these to the real subsystems.
|
|
14
|
+
*/
|
|
15
|
+
export interface RelayReinjectSeams {
|
|
16
|
+
/**
|
|
17
|
+
* Re-admit on the routing key (allowQueue:false — same non-queueing gate the
|
|
18
|
+
* live relay path uses). A re-shed maps the reinject to `shed` so the replayer
|
|
19
|
+
* reverts the row to `buffered`.
|
|
20
|
+
*/
|
|
21
|
+
admit: (routingKey: string) => Promise<AdmitResult>;
|
|
22
|
+
/** Re-verify the raw body against the stored headers. */
|
|
23
|
+
verify: (d: OverflowDelivery, body: Buffer) => Promise<RelayVerifyResult>;
|
|
24
|
+
/** Resolve the provider string for a routing key (bundle → prefix fallback). */
|
|
25
|
+
resolveProvider: (routingKey: string) => string;
|
|
26
|
+
/** Process a verified, normalized delivery through the relay ingest pipeline. */
|
|
27
|
+
process: (info: WebhookInfo) => Promise<WebhookIngestOutcome>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse a captured relay body into a payload object, mirroring the live relay
|
|
31
|
+
* path's content-type handling: JSON (or empty content-type) → parsed object;
|
|
32
|
+
* anything else → `{ rawBody, contentType }`. An empty body is an empty object.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseRelayPayload(body: Buffer, headers: Record<string, string>): Record<string, unknown>;
|
|
35
|
+
/**
|
|
36
|
+
* Build the relay-origin overflow re-injector. Re-admits on the routing key,
|
|
37
|
+
* re-verifies the stored raw body (relay deliveries are captured pre-verify),
|
|
38
|
+
* normalizes it, and processes it through the admission-gated relay pipeline.
|
|
39
|
+
* A re-shed maps to `shed` (revert); a verify miss maps to `skipped` (terminal
|
|
40
|
+
* — the delivery is no longer routable, so it is not retried forever).
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildRelayReinject(seams: RelayReinjectSeams): ReinjectFn;
|
|
43
|
+
//# sourceMappingURL=relay-reinject.d.ts.map
|
|
@@ -20,9 +20,13 @@ export declare class InMemoryJobQueue {
|
|
|
20
20
|
enqueue(input: QueuedJobInput): Promise<string>;
|
|
21
21
|
/**
|
|
22
22
|
* Returns a generated UUID for direct-dispatch tracking, or honors the
|
|
23
|
-
* caller's pre-allocated jobId when set (cluster reroute path).
|
|
23
|
+
* caller's pre-allocated jobId when set (cluster reroute path). The in-memory
|
|
24
|
+
* queue has no unique-key constraint, so an insert is always treated as new.
|
|
24
25
|
*/
|
|
25
|
-
insertDispatched(input: QueuedJobInput): Promise<
|
|
26
|
+
insertDispatched(input: QueuedJobInput, _agentId: string): Promise<{
|
|
27
|
+
id: string;
|
|
28
|
+
inserted: boolean;
|
|
29
|
+
}>;
|
|
26
30
|
/**
|
|
27
31
|
* Dequeue the first pending job matching the given labels.
|
|
28
32
|
*
|
|
@@ -111,12 +115,13 @@ export declare class InMemoryJobQueue {
|
|
|
111
115
|
/** Always returns false. */
|
|
112
116
|
markFailedIfRecovering(_jobId: string, _reason: string): Promise<boolean>;
|
|
113
117
|
/** Always returns false. */
|
|
114
|
-
markDispatchedIfRecovering(_jobId: string): Promise<boolean>;
|
|
118
|
+
markDispatchedIfRecovering(_jobId: string, _agentId: string): Promise<boolean>;
|
|
115
119
|
/** Always returns empty array. */
|
|
116
120
|
getJobsByStatus(_status: DispatchQueueStatus): Promise<Array<{
|
|
117
121
|
id: string;
|
|
118
122
|
runId: string;
|
|
119
123
|
status: DispatchQueueStatus;
|
|
124
|
+
agentId: string | null;
|
|
120
125
|
}>>;
|
|
121
126
|
/** No-op — nothing to expire. */
|
|
122
127
|
markExpired(): Promise<number>;
|