@kici-dev/orchestrator 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__test-helpers__/fake-scaler-state-store.d.ts +24 -0
- package/dist/__test-helpers__/mock-db-query.d.ts +130 -0
- package/dist/__test-helpers__/mock-db.d.ts +27 -0
- package/dist/agent/agent-version.d.ts +34 -0
- package/dist/agent/dispatcher.d.ts +151 -13
- package/dist/agent/host-roster.d.ts +37 -5
- package/dist/agent/registry.d.ts +2 -0
- package/dist/app.d.ts +56 -7
- package/dist/approvals/apply-decision.d.ts +67 -19
- package/dist/approvals/held-run-release-wiring.d.ts +45 -0
- package/dist/approvals/independent-wiring.d.ts +55 -0
- package/dist/approvals/resume-router.d.ts +9 -0
- package/dist/approvals/triggerer-subject.d.ts +37 -0
- package/dist/cache/dep-cache.d.ts +54 -10
- package/dist/cache/global-eval-round-cache.d.ts +95 -0
- package/dist/cache/index.d.ts +3 -0
- package/dist/cache/pending-global-evals.d.ts +42 -0
- package/dist/cache/pending-inits.d.ts +10 -0
- package/dist/cli/api-client.d.ts +18 -0
- package/dist/cli/commands/cluster-settings.d.ts +52 -3
- package/dist/cli/commands/diagnose.d.ts +6 -0
- package/dist/cli/commands/held-run.d.ts +58 -0
- package/dist/cli/commands/runs.d.ts +1 -0
- package/dist/cli/commands/trust-policy.d.ts +117 -12
- package/dist/cli/kici-admin.d.ts +10 -0
- package/dist/cli.js +2770 -938
- package/dist/cluster/cluster-identity.d.ts +3 -3
- package/dist/cluster/cluster-settings-reader.d.ts +59 -1
- package/dist/cluster/coordinator.d.ts +44 -0
- package/dist/cluster/index.d.ts +4 -0
- package/dist/cluster/peer-handler.d.ts +19 -0
- package/dist/cluster/peer-registry.d.ts +17 -0
- package/dist/cluster/plan-headroom-store.d.ts +26 -0
- package/dist/cluster/worker-eviction.d.ts +69 -0
- package/dist/cold-store/load-event-log-range.d.ts +10 -3
- package/dist/cold-store/load-secret-audit-log-range.d.ts +4 -3
- package/dist/cold-store/tables/secret-audit-log.d.ts +4 -3
- package/dist/config.d.ts +48 -21
- package/dist/content-requirements-cache.d.ts +55 -0
- package/dist/contexts/held-runs.d.ts +123 -16
- package/dist/contexts/protection/aggregate.d.ts +3 -2
- package/dist/contexts/protection/branch-gate.d.ts +15 -0
- package/dist/contexts/protection/concurrency-gate.d.ts +8 -2
- package/dist/contexts/protection/pipeline.d.ts +18 -0
- package/dist/contexts/release-queued-holds.d.ts +35 -0
- package/dist/dashboard/attestation-filters.d.ts +8 -0
- package/dist/dashboard/handler.d.ts +6 -24
- package/dist/db/migrations/109_cluster_settings_cache_knobs.d.ts +4 -0
- package/dist/db/migrations/110_cluster_settings_global_eval_knobs.d.ts +4 -0
- package/dist/db/migrations/111_cluster_settings_global_eval_wait.d.ts +4 -0
- package/dist/db/migrations/112_execution_runs_workflow_repo.d.ts +4 -0
- package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +30 -0
- package/dist/db/migrations/114_ingest_queue_claim.d.ts +4 -0
- package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +9 -0
- package/dist/db/migrations/116_org_plan_headroom.d.ts +4 -0
- package/dist/db/migrations/117_invoke_gate_proxy_jobs.d.ts +4 -0
- package/dist/db/migrations/118_invoke_gate_scheduling.d.ts +4 -0
- package/dist/db/migrations/119_scaler_ha_ownership.d.ts +4 -0
- package/dist/db/migrations/120_cluster_settings_scaler_reaper.d.ts +4 -0
- package/dist/db/migrations/121_org_settings_allow_untrusted_dockerfile_builds.d.ts +19 -0
- package/dist/db/migrations/122_host_roster_scaler_managed.d.ts +25 -0
- package/dist/db/migrations/123_workflow_registrations_default_branch.d.ts +24 -0
- package/dist/db/migrations/124_cluster_settings_provision_backoff.d.ts +4 -0
- package/dist/db/migrations/125_org_trust_directory.d.ts +30 -0
- package/dist/db/migrations/126_held_runs_posted_pending_check.d.ts +28 -0
- package/dist/db/migrations/127_org_trust_policy_approval_expiry_seconds.d.ts +26 -0
- package/dist/db/migrations/128_execution_runs_global_eval_round.d.ts +23 -0
- package/dist/db/migrations/129_execution_runs_dispatch_routing_key.d.ts +24 -0
- package/dist/db/migrations/130_scaler_provision_outcomes.d.ts +32 -0
- package/dist/db/types.d.ts +428 -12
- package/dist/entry-helpers.d.ts +28 -0
- package/dist/events/event-emitter.d.ts +22 -0
- package/dist/events/event-router.d.ts +87 -1
- package/dist/events/types.d.ts +2 -23
- package/dist/git/credential-broker.d.ts +94 -0
- package/dist/git/inherited-secret.d.ts +24 -0
- package/dist/git/installation-token.d.ts +38 -0
- package/dist/git/job-context.d.ts +13 -0
- package/dist/index.js +324 -84
- package/dist/metrics/agent-metrics-aggregator.d.ts +4 -4
- package/dist/metrics/prometheus.d.ts +170 -3
- package/dist/oidc/oidc-mint-registration.d.ts +7 -3
- package/dist/orchestrator-core.d.ts +91 -24
- package/dist/pipeline/content-filter.d.ts +71 -0
- package/dist/pipeline/direct-ingress-deps.d.ts +100 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +521 -11
- package/dist/pipeline/global-eval-round.d.ts +307 -0
- package/dist/pipeline/internal-event-pipeline.d.ts +140 -0
- package/dist/pipeline/invoke-gate.d.ts +164 -0
- package/dist/pipeline/job-contexts.d.ts +16 -17
- package/dist/pipeline/needs-scheduler.d.ts +13 -0
- package/dist/pipeline/process-webhook.d.ts +126 -31
- package/dist/pipeline/processor.d.ts +282 -23
- package/dist/pipeline/rerun.d.ts +21 -0
- package/dist/pipeline/resume-workflow.d.ts +40 -7
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +15 -0
- package/dist/pipeline/security-hold-check.d.ts +217 -0
- package/dist/pipeline/test-pipeline.d.ts +12 -0
- package/dist/pipeline/undispatched-hold-checks.d.ts +23 -0
- package/dist/pipeline/webhook-payload-store.d.ts +20 -0
- package/dist/policy/dashboard-write-policy-listener.d.ts +62 -0
- package/dist/policy/dashboard-write-policy.d.ts +14 -0
- package/dist/provenance/backfill-run.d.ts +10 -1
- package/dist/provider-registry.d.ts +47 -4
- package/dist/providers/github/check-status-poster.d.ts +33 -3
- package/dist/providers/github/commit-message.d.ts +20 -0
- package/dist/providers/github/file-contents.d.ts +40 -0
- package/dist/providers/github/index.d.ts +2 -2
- package/dist/providers/github/normalizer.d.ts +3 -2
- package/dist/providers/local/normalizer.d.ts +3 -5
- package/dist/providers/universal-git/config.d.ts +2 -0
- package/dist/providers/universal-git/index.d.ts +11 -2
- package/dist/providers/universal-git/normalizer.d.ts +10 -0
- package/dist/queue/cleanup.d.ts +7 -1
- package/dist/queue/job-queue.d.ts +112 -7
- package/dist/queue/terminalize-unroutable.d.ts +13 -0
- package/dist/registration/extractor.d.ts +3 -3
- package/dist/registration/registration-index.d.ts +7 -0
- package/dist/registration/registration-run-match.d.ts +47 -0
- package/dist/registration/registration-store.d.ts +22 -0
- package/dist/reporting/check-run-reporter.d.ts +146 -2
- package/dist/reporting/check-run-summary.d.ts +25 -1
- package/dist/reporting/execution-tracker.d.ts +324 -9
- package/dist/reporting/log-chunk-sink.d.ts +8 -5
- package/dist/reporting/run-aggregator.d.ts +4 -14
- package/dist/reporting/step-display-order.d.ts +43 -0
- package/dist/routes/admin-held-runs.d.ts +142 -0
- package/dist/routes/admin-org-settings.d.ts +5 -0
- package/dist/routes/admin-trust-policy.d.ts +34 -6
- package/dist/routes/admin.d.ts +15 -0
- package/dist/scaler/backend-factory.d.ts +55 -0
- package/dist/scaler/bare-metal-backend.d.ts +43 -5
- package/dist/scaler/claim-store.d.ts +119 -0
- package/dist/scaler/config.d.ts +4 -0
- package/dist/scaler/container-backend.d.ts +18 -4
- package/dist/scaler/container-routing.d.ts +23 -0
- package/dist/scaler/container-spawn.d.ts +28 -0
- package/dist/scaler/event-backend.d.ts +124 -0
- package/dist/scaler/event-provision-reaper.d.ts +350 -0
- package/dist/scaler/failure-tracker.d.ts +1 -1
- package/dist/scaler/firecracker-backend.d.ts +33 -6
- package/dist/scaler/index.d.ts +11 -1
- package/dist/scaler/label-matcher.d.ts +4 -3
- package/dist/scaler/manager.d.ts +905 -76
- package/dist/scaler/resolve-container-auth.d.ts +45 -0
- package/dist/scaler/scaler-events.d.ts +11 -0
- package/dist/scaler/scaler-state-store.d.ts +294 -10
- package/dist/scaler/types.d.ts +131 -13
- package/dist/scaler/warm-pool.d.ts +132 -29
- package/dist/security/comment-handler.d.ts +50 -11
- package/dist/security/global-workflow-policy.d.ts +52 -12
- package/dist/security/identity-link.d.ts +60 -0
- package/dist/security/lock-source.d.ts +11 -13
- package/dist/security/reduced-privilege-note.d.ts +59 -0
- package/dist/security/trust-directory-store.d.ts +233 -0
- package/dist/security/trust-policy-gate.d.ts +94 -59
- package/dist/security/trust-policy-store.d.ts +3 -0
- package/dist/security/trust-resolver.d.ts +14 -98
- package/dist/server.d.ts +11 -1
- package/dist/server.js +56329 -42234
- package/dist/stale-detector/gate-deadline-detector.d.ts +52 -0
- package/dist/stale-detector/stale-run-detector.d.ts +61 -3
- package/dist/standalone.js +37619 -23570
- package/dist/webhook/ingest-accept.d.ts +70 -0
- package/dist/webhook/ingest-overflow-buffer.d.ts +35 -4
- package/dist/webhook/ingest-overflow-replayer.d.ts +50 -6
- package/dist/worker/in-memory-job-queue.d.ts +1 -1
- package/dist/ws/agent-handler.d.ts +31 -4
- package/dist/ws/dashboard-context-handler.d.ts +28 -4
- package/dist/ws/dashboard-global-workflows-handler.d.ts +36 -9
- package/dist/ws/execution-status-frame.d.ts +32 -0
- package/dist/ws/failure-messages.d.ts +2 -0
- package/dist/ws/git-credential-relay.d.ts +39 -0
- package/dist/ws/oidc-token-relay.d.ts +6 -11
- package/dist/ws/platform-client.d.ts +68 -9
- package/dist/ws/test-relay-handlers.d.ts +35 -10
- package/installer-image-digests.json +3 -3
- package/package.json +24 -19
- package/sbom.spdx.json +868 -821
- package/dist/approvals/team-membership-lookup.d.ts +0 -13
- package/dist/pipeline/inline-eval.d.ts +0 -44
- package/dist/providers/github/contributor-resolver.d.ts +0 -30
- package/dist/security/contributor-cache.d.ts +0 -83
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { type CheckStatus, type CheckStatusPoster } from '@kici-dev/engine';
|
|
2
|
+
import type { Kysely } from 'kysely';
|
|
3
|
+
import type { Database } from '../db/types.js';
|
|
4
|
+
/** Resolve the check poster of the provider bundle a routing key is served by. */
|
|
5
|
+
export type ResolveCheckStatusPoster = (routingKey: string) => CheckStatusPoster | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* The `held_runs` columns this module reads. A full `HeldRun` row satisfies it,
|
|
8
|
+
* so every caller passes the row it already loaded rather than a projection.
|
|
9
|
+
*/
|
|
10
|
+
export interface SecurityCheckHold {
|
|
11
|
+
id: string;
|
|
12
|
+
org_id: string;
|
|
13
|
+
run_id: string;
|
|
14
|
+
job_id: string;
|
|
15
|
+
hold_scope: string;
|
|
16
|
+
hold_type: string;
|
|
17
|
+
approval_requirement: unknown;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the pending post reached the provider. Required rather than
|
|
20
|
+
* optional so a query that projects columns by name cannot omit it and fall
|
|
21
|
+
* back to the shape derivation without the compiler saying so.
|
|
22
|
+
*/
|
|
23
|
+
posted_pending_check: boolean | null;
|
|
24
|
+
}
|
|
25
|
+
/** How a hold ended, which decides the conclusion, title and summary. */
|
|
26
|
+
export declare enum HoldOutcome {
|
|
27
|
+
/** Released to run — an approver satisfied it. */
|
|
28
|
+
Approved = "approved",
|
|
29
|
+
/** Refused by an approver. */
|
|
30
|
+
Rejected = "rejected",
|
|
31
|
+
/** Nobody answered inside the approval window. */
|
|
32
|
+
Expired = "expired"
|
|
33
|
+
}
|
|
34
|
+
/** Why {@link settleSecurityHoldCheck} did or did not write the check. */
|
|
35
|
+
export declare enum SecurityCheckSettlement {
|
|
36
|
+
/** A terminal status was written. */
|
|
37
|
+
Posted = "posted",
|
|
38
|
+
/** This hold posted no pending check, so it has none to terminalize. */
|
|
39
|
+
NotOwned = "not-owned",
|
|
40
|
+
/** The caller already wrote this commit's check earlier in the same pass. */
|
|
41
|
+
AlreadySettled = "already-settled",
|
|
42
|
+
/** Another pending hold on the same commit still owns the check. */
|
|
43
|
+
Contended = "contended",
|
|
44
|
+
/** The hold's run row is gone, so the commit cannot be named. */
|
|
45
|
+
NoCommit = "no-commit",
|
|
46
|
+
/** No provider bundle serves the run's routing key any more. */
|
|
47
|
+
NoPoster = "no-poster",
|
|
48
|
+
/**
|
|
49
|
+
* The settlement could not complete — the provider refused the write, or the
|
|
50
|
+
* hold row did not carry the columns the ownership predicate reads.
|
|
51
|
+
*/
|
|
52
|
+
Failed = "failed"
|
|
53
|
+
}
|
|
54
|
+
export interface SettleSecurityCheckResult {
|
|
55
|
+
outcome: SecurityCheckSettlement;
|
|
56
|
+
/** Whether a terminal status actually reached the provider. */
|
|
57
|
+
posted: boolean;
|
|
58
|
+
/** `owner/repo@sha`, once the hold's commit resolved. */
|
|
59
|
+
commit?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Whether this hold put a pending `KiCI Security` check on its commit, and so
|
|
63
|
+
* has one to terminalize when it ends.
|
|
64
|
+
*
|
|
65
|
+
* `posted_pending_check` is the answer whenever the row carries one: it is
|
|
66
|
+
* written `true` only after the provider accepted the post, so it records what
|
|
67
|
+
* HAPPENED. Everything below records what the code INTENDED, which is a
|
|
68
|
+
* different question and answers the wrong way twice — a post the provider
|
|
69
|
+
* refused, and a hold reached with no check poster in `ctx.bundle`, both leave
|
|
70
|
+
* a shape that says "posted" and a commit that has nothing. Terminalizing then
|
|
71
|
+
* CREATES the check run, so the mirror of the stuck-check leak is a fabricated
|
|
72
|
+
* failing check on a pull request.
|
|
73
|
+
*
|
|
74
|
+
* The shape derivation stays for `null` — a row written before the column
|
|
75
|
+
* existed, for which no fact was recorded and an inference is all there is.
|
|
76
|
+
*
|
|
77
|
+
* Three sites post that pending status, and the derivation is read off them
|
|
78
|
+
* rather than off the queue type — which cannot make the distinction, because a
|
|
79
|
+
* workflow install gate whose context protection rule is security-typed carries
|
|
80
|
+
* `queue_type = 'security'` and posts nothing at all.
|
|
81
|
+
*
|
|
82
|
+
* | Hold | Written by | Posts pending? | Recognised here by |
|
|
83
|
+
* |---|---|---|---|
|
|
84
|
+
* | org trust policy's PR-wide hold | `holdRunForSecurityPolicy` | yes | `job_id` is a `SECURITY_HOLD_JOB_IDS` sentinel |
|
|
85
|
+
* | workflow install gate | `holdWorkflowForInstallGate` | no | `job_id` is `installGateJobId(name)` |
|
|
86
|
+
* | SDK workflow `requireApproval` | `holdJobForApproval` | yes | carries an `approval_requirement` |
|
|
87
|
+
* | context reviewer hold | `holdJobForApproval` | yes | carries an `approval_requirement` |
|
|
88
|
+
* | SDK job `requireApproval` | `holdJobForApproval` | yes | carries an `approval_requirement` |
|
|
89
|
+
* | context security hold | the per-env gate | yes | job scope + `hold_type = security` |
|
|
90
|
+
* | wait-timer / concurrency hold | the per-env gate | no | none of the above matches |
|
|
91
|
+
* | step approval | `StepApprovalBridge.request` | no | step scope |
|
|
92
|
+
*
|
|
93
|
+
* `approval_requirement` is what `createHold` writes and `create` does not, so
|
|
94
|
+
* it identifies exactly the rows `holdJobForApproval` wrote through the
|
|
95
|
+
* approval path — the site whose post is guarded by `if (hold && …)`. The two
|
|
96
|
+
* other `createHold` callers are excluded above it: the install gate by its job
|
|
97
|
+
* id, the step bridge by its scope.
|
|
98
|
+
*/
|
|
99
|
+
export declare function postedPendingSecurityCheck(hold: SecurityCheckHold): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The terminal summary for a hold that ended, in the one vocabulary both check
|
|
102
|
+
* families use: `cancelled` for a rejection, `timed_out` for an elapsed window,
|
|
103
|
+
* `success` for an approval.
|
|
104
|
+
*
|
|
105
|
+
* The subject follows the hold's scope on every outcome, because the same event
|
|
106
|
+
* means different things at each: a workflow-scoped hold owns the whole run,
|
|
107
|
+
* while a job-scoped one owns one job and says nothing about the run's other
|
|
108
|
+
* jobs — including a step-approval hold that is still pending, which a run-wide
|
|
109
|
+
* "no longer waiting for approval" would contradict.
|
|
110
|
+
*
|
|
111
|
+
* `actor` names whoever ended the hold, on an approve and on a reject alike.
|
|
112
|
+
* Only an expiry has none: nobody answered, which is what expiry means. A
|
|
113
|
+
* rejecter whose surface already writes its own attribution into `reason` (the
|
|
114
|
+
* `/kici reject` handler builds "Rejected by alice via /kici reject") passes no
|
|
115
|
+
* `actor`, so the sentence lands once rather than twice.
|
|
116
|
+
*
|
|
117
|
+
* **`actor` is a display name, and it is published verbatim on a public commit
|
|
118
|
+
* check.** It must never be an opaque identity-provider subject id: a surface
|
|
119
|
+
* that holds one — the dashboard / CLI / MCP applier, which decides by KiCI
|
|
120
|
+
* user id — resolves it against the org's identity directory first and passes
|
|
121
|
+
* nothing when that resolves to no single name. Omitting the attribution reads
|
|
122
|
+
* as "an approver"; leaking the subject reads as `Approved by
|
|
123
|
+
* 8f3a-…-uuid`, on a pull request anyone can open.
|
|
124
|
+
*
|
|
125
|
+
* `reason` is normalized to end in terminal punctuation — a rejecter's own
|
|
126
|
+
* sentence carries none, and without one it runs straight into what follows.
|
|
127
|
+
*/
|
|
128
|
+
export declare function buildHoldEndedSummary(args: {
|
|
129
|
+
outcome: HoldOutcome;
|
|
130
|
+
scope: string;
|
|
131
|
+
reason?: string | undefined;
|
|
132
|
+
actor?: string | undefined;
|
|
133
|
+
via?: string | undefined;
|
|
134
|
+
}): string;
|
|
135
|
+
/**
|
|
136
|
+
* Terminalize the `KiCI Security` check of a hold that just ended, choosing the
|
|
137
|
+
* conclusion, title and summary from {@link HoldOutcome}.
|
|
138
|
+
*
|
|
139
|
+
* The single entry point for every surface that ends a hold — the `/kici`
|
|
140
|
+
* comment handler, the dashboard / CLI / MCP applier, and the stale detector's
|
|
141
|
+
* approval-window sweep — so those surfaces cannot render one event three ways.
|
|
142
|
+
*/
|
|
143
|
+
export declare function settleSecurityCheckForOutcome(args: {
|
|
144
|
+
db: Kysely<Database> | undefined;
|
|
145
|
+
resolvePoster: ResolveCheckStatusPoster | undefined;
|
|
146
|
+
hold: SecurityCheckHold;
|
|
147
|
+
outcome: HoldOutcome;
|
|
148
|
+
reason?: string | undefined;
|
|
149
|
+
actor?: string | undefined;
|
|
150
|
+
via?: string | undefined;
|
|
151
|
+
excludeHoldIds?: readonly string[] | undefined;
|
|
152
|
+
skipCommits?: ReadonlySet<string> | undefined;
|
|
153
|
+
}): Promise<SettleSecurityCheckResult>;
|
|
154
|
+
/**
|
|
155
|
+
* The dashboard / CLI / MCP applier's entry point into
|
|
156
|
+
* {@link settleSecurityCheckForOutcome}.
|
|
157
|
+
*
|
|
158
|
+
* That applier decides by KiCI user id, so the only actor it holds is an opaque
|
|
159
|
+
* identity-provider subject — and this summary is published verbatim on a public
|
|
160
|
+
* commit check. `resolveDisplayName` maps the subject onto the account name the
|
|
161
|
+
* org's identity directory links it to; when it names none, the attribution is
|
|
162
|
+
* DROPPED rather than falling back to the subject. So an approve reads
|
|
163
|
+
* "Approved by an approver" at worst, never "Approved by 8f3a-…-uuid".
|
|
164
|
+
*
|
|
165
|
+
* Separate from its caller so the resolve-or-drop step is a unit under test
|
|
166
|
+
* rather than a line in the composition root.
|
|
167
|
+
*/
|
|
168
|
+
export declare function settleSecurityCheckForDecision(args: {
|
|
169
|
+
db: Kysely<Database> | undefined;
|
|
170
|
+
resolvePoster: ResolveCheckStatusPoster | undefined;
|
|
171
|
+
/** Subject id → the linked account name, or undefined for no single name. */
|
|
172
|
+
resolveDisplayName: (actorSub: string) => string | undefined;
|
|
173
|
+
hold: SecurityCheckHold;
|
|
174
|
+
outcome: HoldOutcome;
|
|
175
|
+
/** Omitted where the summary must match one another writer built without it. */
|
|
176
|
+
actorSub?: string | undefined;
|
|
177
|
+
reason?: string | undefined;
|
|
178
|
+
}): Promise<SettleSecurityCheckResult>;
|
|
179
|
+
/**
|
|
180
|
+
* Terminalize the `KiCI Security` check of a hold that just ended, under a
|
|
181
|
+
* caller-supplied status and copy.
|
|
182
|
+
*
|
|
183
|
+
* Used directly where one summary has to reach BOTH check families — a rejected
|
|
184
|
+
* workflow-scoped hold reports the same sentence on `KiCI Security` and on the
|
|
185
|
+
* `kici/…` runs of the same event, and that sameness is asserted rather than
|
|
186
|
+
* assumed. Everything else goes through {@link settleSecurityCheckForOutcome}.
|
|
187
|
+
*
|
|
188
|
+
* Call it AFTER the hold's own row has left `pending` (every caller does: the
|
|
189
|
+
* applier flips inside `recordAndReject` / `recordAndRelease`, the comment
|
|
190
|
+
* handler inside `reject` / `approveByQueueType`) — and, on an approve, BEFORE
|
|
191
|
+
* the resume, so a replayed dispatch that holds again overwrites this terminal
|
|
192
|
+
* status with its own pending one rather than the other way round. The ending
|
|
193
|
+
* hold's own id is excluded from the contention query regardless, so a sweep
|
|
194
|
+
* that has not yet flipped its batch can name it in `excludeHoldIds`.
|
|
195
|
+
*
|
|
196
|
+
* Never throws: terminalizing a check run is a reporting courtesy on a path
|
|
197
|
+
* whose real job is to terminalize the hold, and a provider error must not stop
|
|
198
|
+
* that. The returned `posted` is what a caller binds its own suppression to —
|
|
199
|
+
* it says a check was written, not merely that a delegate resolved.
|
|
200
|
+
*/
|
|
201
|
+
export declare function settleSecurityHoldCheck(args: {
|
|
202
|
+
db: Kysely<Database> | undefined;
|
|
203
|
+
resolvePoster: ResolveCheckStatusPoster | undefined;
|
|
204
|
+
hold: SecurityCheckHold;
|
|
205
|
+
status: CheckStatus;
|
|
206
|
+
title: string;
|
|
207
|
+
summary: string;
|
|
208
|
+
excludeHoldIds?: readonly string[] | undefined;
|
|
209
|
+
/**
|
|
210
|
+
* Commits this caller already wrote in the same pass. A sweep that ends
|
|
211
|
+
* several holds on one commit shares one check run between them, and every
|
|
212
|
+
* hold in it carries the same conclusion and summary — so the second write
|
|
213
|
+
* would be a byte-identical provider round-trip.
|
|
214
|
+
*/
|
|
215
|
+
skipCommits?: ReadonlySet<string> | undefined;
|
|
216
|
+
}): Promise<SettleSecurityCheckResult>;
|
|
217
|
+
//# sourceMappingURL=security-hold-check.d.ts.map
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* - direct workflow execution (bypass trigger matching) is supported.
|
|
23
23
|
*/
|
|
24
24
|
import { type ProcessingDeps } from './processor.js';
|
|
25
|
+
import { type ActorPrincipal } from '@kici-dev/engine';
|
|
25
26
|
import type { CheckMode, HostTargetSelector } from '@kici-dev/engine';
|
|
26
27
|
/**
|
|
27
28
|
* Input for a test trigger request.
|
|
@@ -58,6 +59,17 @@ export interface TestTriggerInput {
|
|
|
58
59
|
};
|
|
59
60
|
/** Request trace ID from the HTTP request. */
|
|
60
61
|
requestId: string;
|
|
62
|
+
/**
|
|
63
|
+
* The principal that initiated this run, relayed by the Platform on
|
|
64
|
+
* `test.relay.trigger` (where the wire schema has always required it).
|
|
65
|
+
*
|
|
66
|
+
* Required rather than optional: the relay handler is the only production
|
|
67
|
+
* caller, so there is no path that legitimately lacks an actor, and an
|
|
68
|
+
* optional field would let a future caller silently drop attribution — which
|
|
69
|
+
* is exactly how `execution_runs.triggered_by` stayed NULL for every remote
|
|
70
|
+
* test run while the column claimed to hold the initiator.
|
|
71
|
+
*/
|
|
72
|
+
actor: ActorPrincipal;
|
|
61
73
|
/** JSON-stringified lock file content for local repos with no remote. */
|
|
62
74
|
inlineLockFile?: string;
|
|
63
75
|
/** When true, repo has no remote -- skip provider lookup, skip clone. */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CheckRunConclusion } from '@kici-dev/engine';
|
|
2
|
+
import type { Kysely } from 'kysely';
|
|
3
|
+
import type { Database } from '../db/types.js';
|
|
4
|
+
import type { CheckRunReporter } from '../reporting/check-run-reporter.js';
|
|
5
|
+
/**
|
|
6
|
+
* Complete the check runs of `runId`'s stored workflow dispatch, if it has one.
|
|
7
|
+
*
|
|
8
|
+
* A run with no pending workflow context never held at workflow scope (or its
|
|
9
|
+
* context was already consumed by a resume), so there is nothing to close and
|
|
10
|
+
* this is a no-op. Call it BEFORE `deletePendingWorkflowContext` — the context
|
|
11
|
+
* is the only place the check-run names can still be derived from.
|
|
12
|
+
*
|
|
13
|
+
* Never throws: closing a check run is a reporting courtesy on a path whose real
|
|
14
|
+
* job is to terminalize the run, and a provider error must not stop that.
|
|
15
|
+
*/
|
|
16
|
+
export declare function completeUndispatchedHoldChecks(args: {
|
|
17
|
+
db: Kysely<Database> | undefined;
|
|
18
|
+
checkRunReporter: CheckRunReporter | undefined;
|
|
19
|
+
runId: string;
|
|
20
|
+
conclusion: CheckRunConclusion;
|
|
21
|
+
summary: string;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=undispatched-hold-checks.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LogStorage } from '../reporting/log-storage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Object-storage key holding the webhook payload for a run. Shared by the
|
|
4
|
+
* writers and by the re-run path that copies a payload forward, so the layout
|
|
5
|
+
* is stated once.
|
|
6
|
+
*/
|
|
7
|
+
export declare function webhookPayloadPath(runId: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Store a run's triggering webhook payload, best-effort.
|
|
10
|
+
*
|
|
11
|
+
* A failure is logged and swallowed: the payload is a debugging aid, and losing
|
|
12
|
+
* it must never cost the run that was about to execute. A no-op when the
|
|
13
|
+
* orchestrator has no object storage configured.
|
|
14
|
+
*/
|
|
15
|
+
export declare function storeWebhookPayload(args: {
|
|
16
|
+
logStorage: LogStorage | undefined;
|
|
17
|
+
runId: string;
|
|
18
|
+
payload: unknown;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=webhook-payload-store.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-coordinator propagation of dashboard-write policy changes.
|
|
3
|
+
*
|
|
4
|
+
* Sister to `GenericSourcesChangeListener`
|
|
5
|
+
* (`packages/orchestrator/src/webhook/generic-sources-listener.ts`), which
|
|
6
|
+
* owns the `generic_sources_change` channel. This listener owns
|
|
7
|
+
* `dashboard_write_policy_change` — the channel `setDashboardWritePolicy`
|
|
8
|
+
* emits from inside its own write transaction.
|
|
9
|
+
*
|
|
10
|
+
* The problem it solves: `dashboardWritePolicyEvents` is a per-process
|
|
11
|
+
* `EventEmitter`, so only the coordinator that served the `kici-admin`
|
|
12
|
+
* write learned about a flip. Its siblings kept serving a stale cached map
|
|
13
|
+
* from their own policy gate for up to the cache TTL, and — worse — kept
|
|
14
|
+
* advertising the stale map to the control plane indefinitely, because
|
|
15
|
+
* capabilities are pushed on change and on reconnect, never polled. The
|
|
16
|
+
* control plane caches capabilities per orchestrator connection and resolves
|
|
17
|
+
* a cluster name to whichever of its connections it finds first, so a policy
|
|
18
|
+
* flip could be invisible to the dashboard for as long as the cluster stayed
|
|
19
|
+
* up.
|
|
20
|
+
*
|
|
21
|
+
* On NOTIFY:
|
|
22
|
+
* 1. Queue the affected `customer_id` (the channel payload).
|
|
23
|
+
* 2. Debounce 200 ms so rapid flips coalesce into one drain pass.
|
|
24
|
+
* 3. For each queued customer: drop the cached map, re-read the
|
|
25
|
+
* authoritative one from the database, and emit `'changed'` on
|
|
26
|
+
* `dashboardWritePolicyEvents`. The platform-mode boot already
|
|
27
|
+
* subscribes to that event and re-broadcasts `orch.capabilities`.
|
|
28
|
+
*
|
|
29
|
+
* The payload is the customer id alone: every coordinator shares one
|
|
30
|
+
* orchestrator database, so re-reading is both cheap and authoritative,
|
|
31
|
+
* and no wire copy of the map can go stale in flight.
|
|
32
|
+
*
|
|
33
|
+
* The writing coordinator receives its own NOTIFY too. That is deliberate
|
|
34
|
+
* and harmless — it already emitted the event in-process, and the second
|
|
35
|
+
* emit produces an identical capability broadcast.
|
|
36
|
+
*/
|
|
37
|
+
import type pg from 'pg';
|
|
38
|
+
import type { Kysely } from 'kysely';
|
|
39
|
+
import type { Database } from '../db/types.js';
|
|
40
|
+
export interface DashboardWritePolicyChangeListenerOptions {
|
|
41
|
+
/** Raw pg pool — a dedicated PoolClient is checked out for LISTEN. */
|
|
42
|
+
pool: pg.Pool;
|
|
43
|
+
/** Used to re-read the authoritative policy map on each NOTIFY. */
|
|
44
|
+
db: Kysely<Database>;
|
|
45
|
+
/** Coalesce window for rapid NOTIFYs against the same customer. Default 200 ms. */
|
|
46
|
+
debounceMs?: number;
|
|
47
|
+
}
|
|
48
|
+
export declare class DashboardWritePolicyChangeListener {
|
|
49
|
+
private readonly opts;
|
|
50
|
+
private client;
|
|
51
|
+
private readonly pending;
|
|
52
|
+
private debounceTimer;
|
|
53
|
+
private readonly debounceMs;
|
|
54
|
+
constructor(opts: DashboardWritePolicyChangeListenerOptions);
|
|
55
|
+
/** Open the dedicated client and subscribe. */
|
|
56
|
+
start(): Promise<void>;
|
|
57
|
+
stop(): Promise<void>;
|
|
58
|
+
private scheduleDrain;
|
|
59
|
+
/** Visible for tests — drain the queued customer ids synchronously. */
|
|
60
|
+
drain(): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=dashboard-write-policy-listener.d.ts.map
|
|
@@ -23,10 +23,24 @@ import { type Kysely } from 'kysely';
|
|
|
23
23
|
import { DashboardWriteOperation, type DashboardWritePolicyMap, type DashboardWritePolicyState } from '@kici-dev/engine/protocol/dashboard-write-operations';
|
|
24
24
|
import type { Database } from '../db/types.js';
|
|
25
25
|
import type { ActorPrincipal } from '@kici-dev/engine';
|
|
26
|
+
/**
|
|
27
|
+
* Postgres `LISTEN/NOTIFY` channel carrying policy changes across the
|
|
28
|
+
* cluster. The payload is the `customer_id` alone — every coordinator
|
|
29
|
+
* shares one orchestrator database, so each listener re-reads the
|
|
30
|
+
* authoritative map for itself rather than trusting a wire copy.
|
|
31
|
+
*
|
|
32
|
+
* `DashboardWritePolicyChangeListener` (`./dashboard-write-policy-listener.ts`)
|
|
33
|
+
* is the consumer.
|
|
34
|
+
*/
|
|
35
|
+
export declare const DASHBOARD_WRITE_POLICY_CHANNEL = "dashboard_write_policy_change";
|
|
26
36
|
/**
|
|
27
37
|
* Event bus for policy-change notifications. The WS publisher subscribes
|
|
28
38
|
* to `'changed'` so it can broadcast a fresh `orch.capabilities` to
|
|
29
39
|
* Platform whenever the operator flips a switch.
|
|
40
|
+
*
|
|
41
|
+
* The emitter is per-process, so it carries a change only to the peer that
|
|
42
|
+
* served the admin write. The NOTIFY channel above is what reaches the other
|
|
43
|
+
* coordinators, whose listeners then emit this same event locally.
|
|
30
44
|
*/
|
|
31
45
|
export declare const dashboardWritePolicyEvents: EventEmitter<[never]>;
|
|
32
46
|
/**
|
|
@@ -6,6 +6,12 @@ export interface BackfillRunRow {
|
|
|
6
6
|
status: string;
|
|
7
7
|
routing_key: string | null;
|
|
8
8
|
repo_identifier: string | null;
|
|
9
|
+
/**
|
|
10
|
+
* The repository that DEFINES the workflow, recorded only when it differs
|
|
11
|
+
* from `repo_identifier`. A cross-repository global run backfilled without it
|
|
12
|
+
* lands in the Platform mirror as an ordinary per-repository run.
|
|
13
|
+
*/
|
|
14
|
+
workflow_repo_identifier: string | null;
|
|
9
15
|
provider: string | null;
|
|
10
16
|
local_working_tree: boolean | null;
|
|
11
17
|
sha: string | null;
|
|
@@ -33,7 +39,10 @@ export interface BackfillRunDeps {
|
|
|
33
39
|
}
|
|
34
40
|
/**
|
|
35
41
|
* Send one `execution.status` (terminal) followed by one `job.status.forward`
|
|
36
|
-
* per job, populating
|
|
42
|
+
* per job, populating the run and job fields the Platform's `handler.ts` upserts
|
|
43
|
+
* that the local rows can answer for (the trigger metadata a live run carries in
|
|
44
|
+
* memory — trigger event, commit message, re-run lineage — has no column here
|
|
45
|
+
* and is left to the live path).
|
|
37
46
|
* Ordered execution.status FIRST so the run row exists before the job rows
|
|
38
47
|
* reference it. A no-op (throws) when the run is not found locally — the caller
|
|
39
48
|
* leaves the pending row `deferred` with a clear error.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* webhook normalization, lock file fetching, changed files retrieval,
|
|
13
13
|
* clone token creation, and URL building.
|
|
14
14
|
*/
|
|
15
|
-
import type { WebhookNormalizer, LockFileFetcher, ChangedFilesFetcher, CloneTokenProvider, RepoUrlBuilder,
|
|
15
|
+
import type { WebhookNormalizer, LockFileFetcher, FileContentsFetcher, ChangedFilesFetcher, CloneTokenProvider, RepoUrlBuilder, CheckStatusPoster, ProviderType } from '@kici-dev/engine';
|
|
16
16
|
/**
|
|
17
17
|
* Complete set of provider capabilities.
|
|
18
18
|
*
|
|
@@ -24,10 +24,35 @@ import type { WebhookNormalizer, LockFileFetcher, ChangedFilesFetcher, CloneToke
|
|
|
24
24
|
export interface ProviderBundle {
|
|
25
25
|
normalizer: WebhookNormalizer;
|
|
26
26
|
lockFileFetcher?: LockFileFetcher;
|
|
27
|
+
/**
|
|
28
|
+
* Fetches arbitrary file contents at a ref (content-match triggers). Unlike
|
|
29
|
+
* the other fetchers, a GitHub instance is scoped to one installation, so the
|
|
30
|
+
* per-delivery installation id must be known to construct it -- it is wired
|
|
31
|
+
* where that id is in scope, not in the source-level bundle build. Providers
|
|
32
|
+
* that can prebuild one (no per-delivery credential) may set this directly;
|
|
33
|
+
* providers scoped per installation supply {@link fileContentsFetcherFactory}
|
|
34
|
+
* instead.
|
|
35
|
+
*/
|
|
36
|
+
fileContentsFetcher?: FileContentsFetcher;
|
|
37
|
+
/**
|
|
38
|
+
* Builds a per-delivery {@link FileContentsFetcher} from the event
|
|
39
|
+
* credentials (e.g. a GitHub installation id). Returns undefined when the
|
|
40
|
+
* credentials do not carry what the provider needs. The webhook pipeline
|
|
41
|
+
* calls this once per delivery, where the credentials are already resolved.
|
|
42
|
+
*/
|
|
43
|
+
fileContentsFetcherFactory?: (credentials: Record<string, unknown>) => FileContentsFetcher | undefined;
|
|
27
44
|
changedFilesFetcher?: ChangedFilesFetcher;
|
|
28
45
|
cloneTokenProvider?: CloneTokenProvider;
|
|
29
46
|
repoUrlBuilder?: RepoUrlBuilder;
|
|
30
|
-
|
|
47
|
+
/**
|
|
48
|
+
* This provider has a fork model: a head ref can live outside the base repo,
|
|
49
|
+
* so the fork trust policy applies to its pull-request events. True for
|
|
50
|
+
* GitHub. Absent for providers whose trust boundary is something else — a
|
|
51
|
+
* generic source's verification secret, a local source's on-disk ownership —
|
|
52
|
+
* and for universal-git, which reports an `isForkPR` signal that must not
|
|
53
|
+
* gate it.
|
|
54
|
+
*/
|
|
55
|
+
hasForkModel?: boolean;
|
|
31
56
|
checkStatusPoster?: CheckStatusPoster;
|
|
32
57
|
/**
|
|
33
58
|
* Local `file://` in-place profile: this bundle's `repoBasePath` is the
|
|
@@ -79,12 +104,30 @@ export declare class ProviderRegistry {
|
|
|
79
104
|
* prefix. For multi-app, use getByRoutingKey() instead.
|
|
80
105
|
*/
|
|
81
106
|
get(type: ProviderType): ProviderBundle | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Whether a bundle is registered at EXACTLY this routing key.
|
|
109
|
+
*
|
|
110
|
+
* `getByRoutingKey` cannot answer this: it falls back to a provider-type
|
|
111
|
+
* lookup, so it returns a bundle for a key it has never seen. A caller that
|
|
112
|
+
* needs to know whether the source's OWN bundle is present — rather than
|
|
113
|
+
* whether some bundle can be produced — has to ask here.
|
|
114
|
+
*/
|
|
115
|
+
hasExact(routingKey: string): boolean;
|
|
82
116
|
/**
|
|
83
117
|
* Get the provider bundle by routing key.
|
|
84
118
|
* Routing keys have the format "{provider}:{id}" (e.g., "github:12345").
|
|
85
119
|
*
|
|
86
|
-
* Falls back to get(providerType) if exact key is not found,
|
|
87
|
-
*
|
|
120
|
+
* Falls back to get(providerType) if the exact key is not found, for
|
|
121
|
+
* backward compatibility with single-app registration.
|
|
122
|
+
*
|
|
123
|
+
* The fallback is deliberately narrower for a `generic:` key. Such a key is
|
|
124
|
+
* fully qualified (`generic:{orgId}:{sourceId}`), so the type-prefix scan in
|
|
125
|
+
* `get()` cannot be a "the single configured app" shortcut the way it is for
|
|
126
|
+
* `github:` — it returns whichever `generic:`-prefixed bundle happens to sit
|
|
127
|
+
* first in insertion order, which may belong to a different source, or to a
|
|
128
|
+
* different ORGANIZATION. Only the shared default bundle (`generic:default`,
|
|
129
|
+
* the one that genuinely stands in for every plain generic source) is an
|
|
130
|
+
* acceptable stand-in, so that is the only fallback offered here.
|
|
88
131
|
*/
|
|
89
132
|
getByRoutingKey(routingKey: string): ProviderBundle | undefined;
|
|
90
133
|
/**
|
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
* - Security holds (pending): "KiCI Security" — "Held for approval"
|
|
6
6
|
* - Workflow modifications (neutral): "KiCI: Workflow changes"
|
|
7
7
|
* - Org globals skipped by the trust policy (neutral): "KiCI: Organization workflows"
|
|
8
|
+
* - Org global evaluation failed (failure): "KiCI: Organization workflow evaluation"
|
|
8
9
|
* - Approved runs (success) / Rejected/expired runs (failure)
|
|
9
10
|
*
|
|
10
|
-
* `postWorkflowModificationCheck
|
|
11
|
-
* interface-backed (the `CheckStatusPoster`
|
|
12
|
-
* post on their own check names so
|
|
11
|
+
* `postWorkflowModificationCheck`, `postGlobalWorkflowsSkippedCheck`, and
|
|
12
|
+
* `postGlobalEvalFailedCheck` are interface-backed (the `CheckStatusPoster`
|
|
13
|
+
* contract in `@kici-dev/engine`) and post on their own check names so none of
|
|
14
|
+
* them overwrites the security-hold check.
|
|
13
15
|
*
|
|
14
16
|
* Reuses the Octokit infrastructure from auth.ts via createInstallationOctokit.
|
|
15
17
|
* Uses a fixed check name per category so that subsequent updates (approve/reject)
|
|
@@ -47,5 +49,33 @@ export declare class GitHubCheckStatusPoster implements CheckStatusPoster {
|
|
|
47
49
|
* while the run is still held. Always posted as neutral/completed.
|
|
48
50
|
*/
|
|
49
51
|
postGlobalWorkflowsSkippedCheck(repoIdentifier: string, commitSha: string, summary: string, credentials: unknown): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Post the check recording that the pre-run evaluation of the organization's
|
|
54
|
+
* global workflows failed, so none of the workflows it was deciding on ran.
|
|
55
|
+
*
|
|
56
|
+
* Its own check name ("KiCI: Organization workflow evaluation") for the same
|
|
57
|
+
* reason as the notice above: the security-hold check is a single named run
|
|
58
|
+
* per commit which a hold posts as pending and approve / reject later
|
|
59
|
+
* complete, so writing this through `postCheckStatus` would resolve a
|
|
60
|
+
* still-held run's check and unblock a branch protection rule that requires
|
|
61
|
+
* it.
|
|
62
|
+
*
|
|
63
|
+
* Posted as a failure, not a neutral: work the organization asked for did not
|
|
64
|
+
* run, and the reader has to be able to tell that from a clean commit. The
|
|
65
|
+
* name is new, so no existing branch protection rule requires it — a rule
|
|
66
|
+
* only requires check names it was configured with.
|
|
67
|
+
*/
|
|
68
|
+
postGlobalEvalFailedCheck(repoIdentifier: string, commitSha: string, summary: string, credentials: unknown): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Post the success conclusion on the organization-workflow-evaluation check
|
|
71
|
+
* after a re-run of a failed round completed cleanly.
|
|
72
|
+
*
|
|
73
|
+
* Deliberately the SAME check name the failure posts: GitHub keys a check run
|
|
74
|
+
* by its name on a commit, so writing the success under that name is what
|
|
75
|
+
* turns the red check green on the original commit. A second, differently
|
|
76
|
+
* named green check would leave the red one standing and keep a branch
|
|
77
|
+
* protection rule blocked with no way to clear it short of a new commit.
|
|
78
|
+
*/
|
|
79
|
+
postGlobalEvalSucceededCheck(repoIdentifier: string, commitSha: string, summary: string, credentials: unknown): Promise<void>;
|
|
50
80
|
}
|
|
51
81
|
//# sourceMappingURL=check-status-poster.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the commit message lives in a GitHub webhook payload, and the two
|
|
3
|
+
* different readings of it.
|
|
4
|
+
*
|
|
5
|
+
* They differ deliberately. `githubFilterText` feeds the Tier-0 `commitMessage`
|
|
6
|
+
* trigger filter, so it must be the WHOLE message — truncating to the subject
|
|
7
|
+
* line would make a `[skip ci]` marker written in the body invisible to a filter
|
|
8
|
+
* that names it. `githubDisplayMessage` feeds run-display metadata, where a
|
|
9
|
+
* one-line summary is the point.
|
|
10
|
+
*/
|
|
11
|
+
/** Full text a `commitMessage` trigger filter is tested against; undefined when the payload carries none. */
|
|
12
|
+
export declare function githubFilterText(event: string, payload: unknown): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* One-line message for run display: the subject (first line) of a push's
|
|
15
|
+
* head-commit message, the PR title, or the issue title. This is the reading
|
|
16
|
+
* run-display metadata uses, distinct from the full text `githubFilterText`
|
|
17
|
+
* feeds the Tier-0 filter.
|
|
18
|
+
*/
|
|
19
|
+
export declare function githubDisplayMessage(event: string, payload: unknown): string | undefined;
|
|
20
|
+
//# sourceMappingURL=commit-message.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub file contents fetcher.
|
|
3
|
+
*
|
|
4
|
+
* Implements the FileContentsFetcher interface from @kici-dev/engine for GitHub.
|
|
5
|
+
* Fetches an arbitrary file's contents from a GitHub repository at a specific
|
|
6
|
+
* ref via the Contents API, so the orchestrator can evaluate content-match
|
|
7
|
+
* triggers without cloning the repo.
|
|
8
|
+
*/
|
|
9
|
+
import type { FileContentsFetcher } from '@kici-dev/engine';
|
|
10
|
+
import { type GitHubAppConfig } from './auth.js';
|
|
11
|
+
/**
|
|
12
|
+
* GitHub-specific implementation of FileContentsFetcher.
|
|
13
|
+
*
|
|
14
|
+
* The installation id is baked in at construction because the
|
|
15
|
+
* FileContentsFetcher interface is credential-less at call time -- a fetcher
|
|
16
|
+
* instance is scoped to one GitHub App installation.
|
|
17
|
+
*/
|
|
18
|
+
export declare class GitHubFileContentsFetcher implements FileContentsFetcher {
|
|
19
|
+
private readonly config;
|
|
20
|
+
private readonly installationId;
|
|
21
|
+
readonly provider: 'github';
|
|
22
|
+
constructor(config: GitHubAppConfig, installationId: number);
|
|
23
|
+
/**
|
|
24
|
+
* Fetch a file's contents from a GitHub repository at a specific ref.
|
|
25
|
+
*
|
|
26
|
+
* @param owner - Repository owner (e.g. "my-org")
|
|
27
|
+
* @param repo - Repository name (e.g. "my-app")
|
|
28
|
+
* @param path - Repo-relative file path (e.g. ".kici/workflows/ci.ts")
|
|
29
|
+
* @param ref - Git ref (branch, tag, or SHA)
|
|
30
|
+
* @returns `{ present: false }` on 404 / directory; `{ present: true, bytes }`
|
|
31
|
+
* when inline content is returned; `{ present: true }` (no bytes)
|
|
32
|
+
* when the file exists but GitHub omits inline content (files over
|
|
33
|
+
* 1 MiB).
|
|
34
|
+
*/
|
|
35
|
+
getFileContents(owner: string, repo: string, path: string, ref: string): Promise<{
|
|
36
|
+
present: boolean;
|
|
37
|
+
bytes?: string;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=file-contents.d.ts.map
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
* Each class implements a corresponding interface from @kici-dev/engine:
|
|
5
5
|
* - GitHubWebhookNormalizer -> WebhookNormalizer
|
|
6
6
|
* - GitHubLockFileFetcher -> LockFileFetcher
|
|
7
|
+
* - GitHubFileContentsFetcher -> FileContentsFetcher
|
|
7
8
|
* - GitHubChangedFilesFetcher -> ChangedFilesFetcher
|
|
8
9
|
* - GitHubCloneTokenProvider -> CloneTokenProvider
|
|
9
10
|
* - GitHubRepoUrlBuilder -> RepoUrlBuilder
|
|
10
|
-
* - GitHubContributorResolver -> ContributorResolver
|
|
11
11
|
*/
|
|
12
12
|
export { GitHubWebhookNormalizer } from './normalizer.js';
|
|
13
13
|
export { GitHubLockFileFetcher } from './lock-file.js';
|
|
14
|
+
export { GitHubFileContentsFetcher } from './file-contents.js';
|
|
14
15
|
export { GitHubChangedFilesFetcher } from './changed-files.js';
|
|
15
16
|
export { GitHubCloneTokenProvider, createInstallationOctokit } from './auth.js';
|
|
16
17
|
export type { GitHubAppConfig, GitHubCredentials } from './auth.js';
|
|
17
18
|
export { GitHubRepoUrlBuilder } from './repo-url.js';
|
|
18
|
-
export { GitHubContributorResolver } from './contributor-resolver.js';
|
|
19
19
|
export { GitHubCheckStatusPoster } from './check-status-poster.js';
|
|
20
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -74,8 +74,9 @@ export declare class GitHubWebhookNormalizer implements WebhookNormalizer {
|
|
|
74
74
|
*/
|
|
75
75
|
extractCredentials(payload: unknown): Record<string, unknown>;
|
|
76
76
|
/**
|
|
77
|
-
* Map GitHub membership-related webhook events to
|
|
78
|
-
* invalidations. See WebhookNormalizer.getAccessCacheInvalidations
|
|
77
|
+
* Map GitHub membership-related webhook events to permission-cache
|
|
78
|
+
* invalidations. See WebhookNormalizer.getAccessCacheInvalidations, which is
|
|
79
|
+
* deprecated and has no caller.
|
|
79
80
|
*
|
|
80
81
|
* Covered event types:
|
|
81
82
|
*
|
|
@@ -70,8 +70,9 @@ export declare class LocalWebhookNormalizer implements WebhookNormalizer {
|
|
|
70
70
|
*/
|
|
71
71
|
normalizeEvent(eventType: string, _action: string | null, payload: unknown): SimulatedEvent | null;
|
|
72
72
|
/**
|
|
73
|
-
* Map membership-related local-source webhook events to
|
|
74
|
-
* invalidations.
|
|
73
|
+
* Map membership-related local-source webhook events to permission-cache
|
|
74
|
+
* invalidations. See WebhookNormalizer.getAccessCacheInvalidations, which is
|
|
75
|
+
* deprecated and has no caller.
|
|
75
76
|
*
|
|
76
77
|
* Local-source payloads are GitHub-shaped by design, so the mapping
|
|
77
78
|
* mirrors the GitHub normalizer exactly:
|
|
@@ -80,9 +81,6 @@ export declare class LocalWebhookNormalizer implements WebhookNormalizer {
|
|
|
80
81
|
* - `organization`: user-in-org
|
|
81
82
|
* - `membership`: user-in-org
|
|
82
83
|
* - `team` (repo-scoped actions only): repo
|
|
83
|
-
*
|
|
84
|
-
* This lets membership-invalidation paths be exercised through
|
|
85
|
-
* `sendLocalWebhook()` without requiring a real GitHub App.
|
|
86
84
|
*/
|
|
87
85
|
getAccessCacheInvalidations(eventType: string, _action: string | null, payload: unknown): AccessCacheInvalidation[];
|
|
88
86
|
}
|