@kici-dev/engine 0.0.0 → 0.1.1
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/LICENSE +661 -0
- package/README.md +1 -6
- package/dist/audit/access-log-policy.d.ts +97 -0
- package/dist/audit/access-log-policy.js +195 -0
- package/dist/audit/activity.d.ts +156 -0
- package/dist/audit/activity.js +175 -0
- package/dist/audit/retention-policy.d.ts +157 -0
- package/dist/audit/retention-policy.js +364 -0
- package/dist/bundler/index.d.ts +3 -0
- package/dist/bundler/index.js +3 -0
- package/dist/bundler/rolldown-config.d.ts +41 -0
- package/dist/bundler/rolldown-config.js +40 -0
- package/dist/chunk-gOLHoazu.js +4 -0
- package/dist/env/environment-allowlist.d.ts +45 -0
- package/dist/env/environment-allowlist.js +69 -0
- package/dist/environment/index.d.ts +3 -0
- package/dist/environment/index.js +3 -0
- package/dist/environment/scope-resolver.d.ts +35 -0
- package/dist/environment/scope-resolver.js +77 -0
- package/dist/environment/types.d.ts +98 -0
- package/dist/environment/types.js +2 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +45 -0
- package/dist/labels.d.ts +106 -0
- package/dist/labels.js +162 -0
- package/dist/metrics/metric-catalog.generated.d.ts +400 -0
- package/dist/metrics/metric-catalog.generated.js +510 -0
- package/dist/protocol/dashboard-global-workflows.d.ts +9 -0
- package/dist/protocol/dashboard-global-workflows.js +3 -0
- package/dist/protocol/event-log-payload.d.ts +16 -0
- package/dist/protocol/event-log-payload.js +21 -0
- package/dist/protocol/messages/access-log.d.ts +545 -0
- package/dist/protocol/messages/access-log.js +175 -0
- package/dist/protocol/messages/actor.d.ts +100 -0
- package/dist/protocol/messages/actor.js +139 -0
- package/dist/protocol/messages/auth.d.ts +25 -0
- package/dist/protocol/messages/auth.js +36 -0
- package/dist/protocol/messages/browser.d.ts +369 -0
- package/dist/protocol/messages/browser.js +225 -0
- package/dist/protocol/messages/capabilities.d.ts +46 -0
- package/dist/protocol/messages/capabilities.js +42 -0
- package/dist/protocol/messages/common.d.ts +53 -0
- package/dist/protocol/messages/common.js +55 -0
- package/dist/protocol/messages/dashboard-global-workflows.d.ts +166 -0
- package/dist/protocol/messages/dashboard-global-workflows.js +80 -0
- package/dist/protocol/messages/dashboard.d.ts +4068 -0
- package/dist/protocol/messages/dashboard.js +1237 -0
- package/dist/protocol/messages/event-log.d.ts +49 -0
- package/dist/protocol/messages/event-log.js +45 -0
- package/dist/protocol/messages/execution-status.d.ts +164 -0
- package/dist/protocol/messages/execution-status.js +166 -0
- package/dist/protocol/messages/join.d.ts +18 -0
- package/dist/protocol/messages/join.js +28 -0
- package/dist/protocol/messages/log-pull.d.ts +27 -0
- package/dist/protocol/messages/log-pull.js +36 -0
- package/dist/protocol/messages/observe.d.ts +75 -0
- package/dist/protocol/messages/observe.js +70 -0
- package/dist/protocol/messages/orchestrator-agent.d.ts +606 -0
- package/dist/protocol/messages/orchestrator-agent.js +481 -0
- package/dist/protocol/messages/peer.d.ts +795 -0
- package/dist/protocol/messages/peer.js +372 -0
- package/dist/protocol/messages/platform-orchestrator.d.ts +1888 -0
- package/dist/protocol/messages/platform-orchestrator.js +379 -0
- package/dist/protocol/messages/run-events.d.ts +155 -0
- package/dist/protocol/messages/run-events.js +115 -0
- package/dist/protocol/messages/saas-orchestrator.d.ts +2179 -0
- package/dist/protocol/messages/source-registration.d.ts +103 -0
- package/dist/protocol/messages/source-registration.js +109 -0
- package/dist/protocol/messages/test-run.d.ts +59 -0
- package/dist/protocol/messages/test-run.js +52 -0
- package/dist/protocol/version.d.ts +12 -0
- package/dist/protocol/version.js +17 -0
- package/dist/provider/changed-files-fetcher.d.ts +24 -0
- package/dist/provider/changed-files-fetcher.js +2 -0
- package/dist/provider/check-run-conclusion.d.ts +15 -0
- package/dist/provider/check-run-conclusion.js +19 -0
- package/dist/provider/check-status-poster.d.ts +15 -0
- package/dist/provider/check-status-poster.js +2 -0
- package/dist/provider/clone-token-provider.d.ts +58 -0
- package/dist/provider/clone-token-provider.js +2 -0
- package/dist/provider/contributor-resolver.d.ts +22 -0
- package/dist/provider/contributor-resolver.js +2 -0
- package/dist/provider/index.d.ts +23 -0
- package/dist/provider/index.js +3 -0
- package/dist/provider/lock-file-fetcher.d.ts +24 -0
- package/dist/provider/lock-file-fetcher.js +2 -0
- package/dist/provider/repo-url-builder.d.ts +35 -0
- package/dist/provider/repo-url-builder.js +2 -0
- package/dist/provider/types.d.ts +9 -0
- package/dist/provider/types.js +2 -0
- package/dist/provider/webhook-normalizer.d.ts +163 -0
- package/dist/provider/webhook-normalizer.js +2 -0
- package/dist/registration/registerable-trigger-type.d.ts +52 -0
- package/dist/registration/registerable-trigger-type.js +56 -0
- package/dist/scaler/resource-types.d.ts +90 -0
- package/dist/scaler/resource-types.js +99 -0
- package/dist/scaler/scaler-backend-type.d.ts +16 -0
- package/dist/scaler/scaler-backend-type.js +20 -0
- package/dist/secrets/index.d.ts +7 -0
- package/dist/secrets/index.js +2 -0
- package/dist/secrets/types.d.ts +138 -0
- package/dist/secrets/types.js +2 -0
- package/dist/state-machine/index.d.ts +2 -0
- package/dist/state-machine/index.js +3 -0
- package/dist/state-machine/machine.d.ts +34 -0
- package/dist/state-machine/machine.js +103 -0
- package/dist/state-machine/types.d.ts +34 -0
- package/dist/state-machine/types.js +15 -0
- package/dist/trigger/decision-trace.d.ts +41 -0
- package/dist/trigger/decision-trace.js +30 -0
- package/dist/trigger/jsonpath-matcher.d.ts +27 -0
- package/dist/trigger/jsonpath-matcher.js +92 -0
- package/dist/trigger/matcher.d.ts +29 -0
- package/dist/trigger/matcher.js +704 -0
- package/dist/trigger/trigger-event-type.d.ts +14 -0
- package/dist/trigger/trigger-event-type.js +66 -0
- package/dist/trigger/types.d.ts +524 -0
- package/dist/trigger/types.js +48 -0
- package/dist/webhook/signature.d.ts +15 -0
- package/dist/webhook/signature.js +32 -0
- package/dist/ws/close-codes.d.ts +28 -0
- package/dist/ws/close-codes.js +33 -0
- package/dist/ws/rate-limiter.d.ts +86 -0
- package/dist/ws/rate-limiter.js +136 -0
- package/dist/ws/ws-like.d.ts +12 -0
- package/dist/ws/ws-like.js +2 -0
- package/package.json +54 -6
- package/sbom.spdx.json +202 -0
- package/index.js +0 -3
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebhookNormalizer interface.
|
|
3
|
+
*
|
|
4
|
+
* Translates provider-specific webhook HTTP requests into KiCI's universal
|
|
5
|
+
* SimulatedEvent format. Each provider implements this to handle its own
|
|
6
|
+
* header conventions, signature schemes, and payload structures.
|
|
7
|
+
*/
|
|
8
|
+
import type { SimulatedEvent } from '../trigger/types.js';
|
|
9
|
+
import type { ProviderType } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Discriminated union describing which `ContributorCache` entries a webhook
|
|
12
|
+
* event invalidates. Returned by `WebhookNormalizer.getAccessCacheInvalidations`.
|
|
13
|
+
*
|
|
14
|
+
* Three scopes:
|
|
15
|
+
* - `repo-user`: a single `{repo, user}` permission changed (e.g. GitHub
|
|
16
|
+
* `member` event on a specific collaborator).
|
|
17
|
+
* - `repo`: every contributor's effective permission on a repo may have
|
|
18
|
+
* shifted (e.g. a team was added/removed from the repo).
|
|
19
|
+
* - `user-in-org`: a user's org membership changed, so any repo under that
|
|
20
|
+
* org may now return a different permission for them.
|
|
21
|
+
*/
|
|
22
|
+
export type AccessCacheInvalidation = {
|
|
23
|
+
kind: 'repo-user';
|
|
24
|
+
repoFullName: string;
|
|
25
|
+
username: string;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'repo';
|
|
28
|
+
repoFullName: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'user-in-org';
|
|
31
|
+
orgLogin: string;
|
|
32
|
+
username: string;
|
|
33
|
+
};
|
|
34
|
+
export interface WebhookNormalizer {
|
|
35
|
+
readonly provider: ProviderType;
|
|
36
|
+
/**
|
|
37
|
+
* Extract a routing key from webhook headers/payload.
|
|
38
|
+
*
|
|
39
|
+
* The routing key uniquely identifies a webhook source within KiCI.
|
|
40
|
+
* Format: "{provider}:{provider-specific-id}"
|
|
41
|
+
*
|
|
42
|
+
* Examples:
|
|
43
|
+
* - GitHub: "github:12345" from X-GitHub-Hook-Installation-Target-ID header
|
|
44
|
+
* - GitLab: "gitlab:67890" from payload.project.id
|
|
45
|
+
* - Bitbucket: "bitbucket:{uuid}" from payload.repository.uuid
|
|
46
|
+
*/
|
|
47
|
+
extractRoutingKey(headers: Record<string, string>, payload: unknown): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Extract a unique delivery ID for deduplication.
|
|
50
|
+
*
|
|
51
|
+
* Examples:
|
|
52
|
+
* - GitHub: X-GitHub-Delivery header
|
|
53
|
+
* - GitLab: X-Gitlab-Event-UUID header
|
|
54
|
+
* - Bitbucket: X-Request-UUID header
|
|
55
|
+
*/
|
|
56
|
+
extractDeliveryId(headers: Record<string, string>): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Extract the event type from headers.
|
|
59
|
+
*
|
|
60
|
+
* Returns the provider-specific event type string (not yet normalized).
|
|
61
|
+
*
|
|
62
|
+
* Examples:
|
|
63
|
+
* - GitHub: X-GitHub-Event header ("push", "pull_request")
|
|
64
|
+
* - GitLab: X-Gitlab-Event header ("Push Hook", "Merge Request Hook")
|
|
65
|
+
* - Bitbucket: X-Event-Key header ("repo:push", "pullrequest:created")
|
|
66
|
+
*/
|
|
67
|
+
extractEventType(headers: Record<string, string>): string | null;
|
|
68
|
+
/**
|
|
69
|
+
* Verify webhook signature or token.
|
|
70
|
+
*
|
|
71
|
+
* Each provider has its own verification scheme:
|
|
72
|
+
* - GitHub: HMAC-SHA256 with X-Hub-Signature-256 header
|
|
73
|
+
* - GitLab: Plain token comparison with X-Gitlab-Token header
|
|
74
|
+
* - Bitbucket: HMAC-SHA256 with X-Hub-Signature header
|
|
75
|
+
*
|
|
76
|
+
* @param body - Raw request body as string
|
|
77
|
+
* @param headers - Request headers (lowercase keys)
|
|
78
|
+
* @param secret - Webhook secret/token configured for this source
|
|
79
|
+
* @returns true if signature/token is valid
|
|
80
|
+
*/
|
|
81
|
+
verifySignature(body: string, headers: Record<string, string>, secret: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Normalize a provider-specific webhook into a SimulatedEvent.
|
|
84
|
+
*
|
|
85
|
+
* Maps provider event types to universal 'pull_request' | 'push' types.
|
|
86
|
+
* Returns null if the event type is not relevant for trigger matching
|
|
87
|
+
* (e.g., GitHub "star" events, GitLab "Pipeline Hook" events).
|
|
88
|
+
*
|
|
89
|
+
* @param eventType - Provider-specific event type (from extractEventType)
|
|
90
|
+
* @param action - Event action/sub-type, if applicable (e.g., "opened" for PRs)
|
|
91
|
+
* @param payload - Raw webhook payload
|
|
92
|
+
* @returns Normalized SimulatedEvent, or null if not matchable
|
|
93
|
+
*/
|
|
94
|
+
normalizeEvent(eventType: string, action: string | null, payload: unknown): SimulatedEvent | null;
|
|
95
|
+
/**
|
|
96
|
+
* Extract the repository identifier from a webhook payload.
|
|
97
|
+
*
|
|
98
|
+
* Returns a string in "owner/repo" format, or null if the payload
|
|
99
|
+
* does not contain repository information (e.g., generic webhooks).
|
|
100
|
+
*
|
|
101
|
+
* Examples:
|
|
102
|
+
* - GitHub: "octocat/Hello-World" from payload.repository.full_name
|
|
103
|
+
* - GitLab: "group/project" from payload.project.path_with_namespace
|
|
104
|
+
* - Generic/internal: may return null if no repo concept
|
|
105
|
+
*/
|
|
106
|
+
extractRepoIdentifier(payload: unknown): string | null;
|
|
107
|
+
/**
|
|
108
|
+
* Extract the commit SHA or ref for lock file fetching from a webhook payload.
|
|
109
|
+
*
|
|
110
|
+
* Returns a commit SHA, branch name, or 'HEAD' as a fallback.
|
|
111
|
+
* Each provider maps event types to the appropriate payload field.
|
|
112
|
+
*
|
|
113
|
+
* Examples:
|
|
114
|
+
* - GitHub push: payload.after
|
|
115
|
+
* - GitHub pull_request: payload.pull_request.head.sha
|
|
116
|
+
* - Generic: 'HEAD' (no ref concept)
|
|
117
|
+
*
|
|
118
|
+
* @param eventType - Provider-specific event type (from extractEventType)
|
|
119
|
+
* @param payload - Raw webhook payload
|
|
120
|
+
*/
|
|
121
|
+
extractRef(eventType: string, payload: unknown): string;
|
|
122
|
+
/**
|
|
123
|
+
* Extract provider-specific credentials from a webhook payload.
|
|
124
|
+
*
|
|
125
|
+
* Returns an object with provider-specific credential fields needed
|
|
126
|
+
* for downstream operations (clone tokens, API calls, etc.).
|
|
127
|
+
*
|
|
128
|
+
* Examples:
|
|
129
|
+
* - GitHub: { installationId: 12345 } from payload.installation.id
|
|
130
|
+
* - Generic: {} (no credentials in payload)
|
|
131
|
+
*/
|
|
132
|
+
extractCredentials(payload: unknown): Record<string, unknown>;
|
|
133
|
+
/**
|
|
134
|
+
* Extract the repository's default branch from the webhook payload.
|
|
135
|
+
*
|
|
136
|
+
* Optional. When implemented, the orchestrator uses this hook to decide
|
|
137
|
+
* whether a push event targets the default branch (required for workflow
|
|
138
|
+
* registration extraction). When omitted, the orchestrator falls back to
|
|
139
|
+
* the hardcoded `payload.repository.default_branch` shape.
|
|
140
|
+
*
|
|
141
|
+
* Returns null when the field is missing or cannot be resolved.
|
|
142
|
+
*/
|
|
143
|
+
extractDefaultBranch?(payload: unknown): string | null;
|
|
144
|
+
/**
|
|
145
|
+
* Map a webhook event to the `ContributorCache` entries it should drop.
|
|
146
|
+
*
|
|
147
|
+
* Optional. When implemented, the orchestrator calls this before
|
|
148
|
+
* `normalizeEvent` and invalidates every returned entry so the next
|
|
149
|
+
* permission check hits the provider API instead of relying on stale
|
|
150
|
+
* cached data. Events that do not imply a permission shift (most events,
|
|
151
|
+
* including `push` / `pull_request` / etc.) should return `[]`.
|
|
152
|
+
*
|
|
153
|
+
* The caller is responsible for pairing the returned entries with the
|
|
154
|
+
* `provider` field of the matched bundle — this method receives no
|
|
155
|
+
* provider argument.
|
|
156
|
+
*
|
|
157
|
+
* @param eventType Provider-specific event type (from extractEventType).
|
|
158
|
+
* @param action Event action/sub-type, if applicable.
|
|
159
|
+
* @param payload Raw webhook payload.
|
|
160
|
+
*/
|
|
161
|
+
getAccessCacheInvalidations?(eventType: string, action: string | null, payload: unknown): AccessCacheInvalidation[];
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=webhook-normalizer.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Trigger types whose owning workflows must be stored in workflow_registrations
|
|
4
|
+
* so the orchestrator can resolve them from an index lookup instead of
|
|
5
|
+
* re-fetching a lock file per inbound event.
|
|
6
|
+
*
|
|
7
|
+
* Two families live in this list:
|
|
8
|
+
*
|
|
9
|
+
* 1. Non-Git-provider triggers (kici_event, schedule, webhook, lifecycle, …)
|
|
10
|
+
* — these have no per-repo lock file pipeline to fall back to, so the
|
|
11
|
+
* registration index is the authoritative source for matching.
|
|
12
|
+
*
|
|
13
|
+
* 2. Git-provider triggers (push, pr, tag, release, …) — these ARE still
|
|
14
|
+
* matched via the per-event lock file pipeline on the same-source path
|
|
15
|
+
* (e.g. a real GitHub push webhook). Registering them in addition is
|
|
16
|
+
* what makes cross-source dispatch work for a generic webhook that
|
|
17
|
+
* targets an externally-hosted repo (phase 28.5): the cross-source
|
|
18
|
+
* branch looks up `(customer_id, repo_identifier)` and reuses the
|
|
19
|
+
* stored `provider_context` (installation id, app id, …) to mint
|
|
20
|
+
* credentials for the actual provider bundle that owns the repo.
|
|
21
|
+
* Without this, a workflow whose only trigger is `push()` is invisible
|
|
22
|
+
* to cross-source dispatch and generic webhooks targeting its repo
|
|
23
|
+
* silently no-op.
|
|
24
|
+
*
|
|
25
|
+
* Access values: RegisterableTriggerType.enum.kici_event, etc.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RegisterableTriggerType: z.ZodEnum<{
|
|
28
|
+
status: "status";
|
|
29
|
+
generic_webhook: "generic_webhook";
|
|
30
|
+
pr: "pr";
|
|
31
|
+
push: "push";
|
|
32
|
+
tag: "tag";
|
|
33
|
+
comment: "comment";
|
|
34
|
+
review: "review";
|
|
35
|
+
review_comment: "review_comment";
|
|
36
|
+
release: "release";
|
|
37
|
+
dispatch: "dispatch";
|
|
38
|
+
create: "create";
|
|
39
|
+
delete: "delete";
|
|
40
|
+
workflow_run: "workflow_run";
|
|
41
|
+
fork: "fork";
|
|
42
|
+
star: "star";
|
|
43
|
+
watch: "watch";
|
|
44
|
+
webhook: "webhook";
|
|
45
|
+
kici_event: "kici_event";
|
|
46
|
+
workflow_complete: "workflow_complete";
|
|
47
|
+
job_complete: "job_complete";
|
|
48
|
+
schedule: "schedule";
|
|
49
|
+
lifecycle: "lifecycle";
|
|
50
|
+
}>;
|
|
51
|
+
export type RegisterableTriggerType = z.infer<typeof RegisterableTriggerType>;
|
|
52
|
+
//# sourceMappingURL=registerable-trigger-type.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/registration/registerable-trigger-type.ts
|
|
4
|
+
/**
|
|
5
|
+
* Trigger types whose owning workflows must be stored in workflow_registrations
|
|
6
|
+
* so the orchestrator can resolve them from an index lookup instead of
|
|
7
|
+
* re-fetching a lock file per inbound event.
|
|
8
|
+
*
|
|
9
|
+
* Two families live in this list:
|
|
10
|
+
*
|
|
11
|
+
* 1. Non-Git-provider triggers (kici_event, schedule, webhook, lifecycle, …)
|
|
12
|
+
* — these have no per-repo lock file pipeline to fall back to, so the
|
|
13
|
+
* registration index is the authoritative source for matching.
|
|
14
|
+
*
|
|
15
|
+
* 2. Git-provider triggers (push, pr, tag, release, …) — these ARE still
|
|
16
|
+
* matched via the per-event lock file pipeline on the same-source path
|
|
17
|
+
* (e.g. a real GitHub push webhook). Registering them in addition is
|
|
18
|
+
* what makes cross-source dispatch work for a generic webhook that
|
|
19
|
+
* targets an externally-hosted repo (phase 28.5): the cross-source
|
|
20
|
+
* branch looks up `(customer_id, repo_identifier)` and reuses the
|
|
21
|
+
* stored `provider_context` (installation id, app id, …) to mint
|
|
22
|
+
* credentials for the actual provider bundle that owns the repo.
|
|
23
|
+
* Without this, a workflow whose only trigger is `push()` is invisible
|
|
24
|
+
* to cross-source dispatch and generic webhooks targeting its repo
|
|
25
|
+
* silently no-op.
|
|
26
|
+
*
|
|
27
|
+
* Access values: RegisterableTriggerType.enum.kici_event, etc.
|
|
28
|
+
*/
|
|
29
|
+
const RegisterableTriggerType = z.enum([
|
|
30
|
+
"kici_event",
|
|
31
|
+
"workflow_complete",
|
|
32
|
+
"job_complete",
|
|
33
|
+
"generic_webhook",
|
|
34
|
+
"schedule",
|
|
35
|
+
"lifecycle",
|
|
36
|
+
"webhook",
|
|
37
|
+
"push",
|
|
38
|
+
"pr",
|
|
39
|
+
"tag",
|
|
40
|
+
"comment",
|
|
41
|
+
"review",
|
|
42
|
+
"review_comment",
|
|
43
|
+
"release",
|
|
44
|
+
"dispatch",
|
|
45
|
+
"create",
|
|
46
|
+
"delete",
|
|
47
|
+
"status",
|
|
48
|
+
"workflow_run",
|
|
49
|
+
"fork",
|
|
50
|
+
"star",
|
|
51
|
+
"watch"
|
|
52
|
+
]);
|
|
53
|
+
//#endregion
|
|
54
|
+
export { RegisterableTriggerType };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=registerable-trigger-type.js.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource request and limit types for jobs and scalers.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth — re-exported from the engine barrel and consumed by:
|
|
5
|
+
* - SDK (`Job` / `JobOptions` `resources` field)
|
|
6
|
+
* - compiler (compile-time validation + lockfile emission)
|
|
7
|
+
* - orchestrator (scaler accounting + backend enforcement)
|
|
8
|
+
* - dashboard (read-only display)
|
|
9
|
+
*
|
|
10
|
+
* Shape is K8s-style requests/limits split:
|
|
11
|
+
* - `requests` drive the scheduler's cap math (per-scaler / per-orch / per-machine).
|
|
12
|
+
* - `limits` drive kernel-side enforcement (Docker memory + nanoCpus, FC memSizeMib + vcpuCount,
|
|
13
|
+
* optional bare-metal systemd-run scope).
|
|
14
|
+
*
|
|
15
|
+
* Mirroring rule (applied at the orchestrator's resolve step):
|
|
16
|
+
* - request-only ⇒ limit = request
|
|
17
|
+
* - limit-only ⇒ request = limit
|
|
18
|
+
* - neither ⇒ scaler default
|
|
19
|
+
* - nothing anywhere ⇒ 0/0 (job counts toward agent-count cap only)
|
|
20
|
+
*/
|
|
21
|
+
import { z } from 'zod';
|
|
22
|
+
/**
|
|
23
|
+
* A single resource specification (cpus + memory).
|
|
24
|
+
*
|
|
25
|
+
* - `cpus`: fractional cores (e.g., 1.5 means 1.5 cores).
|
|
26
|
+
* - `memory`: container-style suffix (e.g., "2g", "512m", "1024k").
|
|
27
|
+
* No K8s "Mi/Gi" units — one parser, one format across the codebase.
|
|
28
|
+
*/
|
|
29
|
+
export interface ResourceSpec {
|
|
30
|
+
/** CPU in fractional cores. */
|
|
31
|
+
cpus?: number;
|
|
32
|
+
/** Memory limit, e.g. "2g", "512m", "1024k". */
|
|
33
|
+
memory?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Per-job resource request (declared in workflow source, threaded through to scaler).
|
|
37
|
+
*
|
|
38
|
+
* `requests` drive scheduling math (cap aggregation).
|
|
39
|
+
* `limits` drive kernel-side enforcement of the spawned agent.
|
|
40
|
+
*/
|
|
41
|
+
export interface ResourceRequest {
|
|
42
|
+
/** Requests drive the scheduler's cap math (per-scaler / per-orch / per-machine). */
|
|
43
|
+
requests?: ResourceSpec;
|
|
44
|
+
/** Limits drive kernel enforcement (Docker memory + nanoCpus, FC memSizeMib + vcpuCount, optional bare-metal systemd-run scope). */
|
|
45
|
+
limits?: ResourceSpec;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Zod schema for a single resource spec (cpus + memory).
|
|
49
|
+
*/
|
|
50
|
+
export declare const resourceSpecSchema: z.ZodObject<{
|
|
51
|
+
cpus: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
53
|
+
}, z.core.$strict>;
|
|
54
|
+
/**
|
|
55
|
+
* Zod schema for the nested request/limit form.
|
|
56
|
+
*/
|
|
57
|
+
export declare const resourceRequestNestedSchema: z.ZodObject<{
|
|
58
|
+
requests: z.ZodOptional<z.ZodObject<{
|
|
59
|
+
cpus: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, z.core.$strict>>;
|
|
62
|
+
limits: z.ZodOptional<z.ZodObject<{
|
|
63
|
+
cpus: z.ZodOptional<z.ZodNumber>;
|
|
64
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
65
|
+
}, z.core.$strict>>;
|
|
66
|
+
}, z.core.$strict>;
|
|
67
|
+
/**
|
|
68
|
+
* Parse a memory string with unit suffix to bytes.
|
|
69
|
+
*
|
|
70
|
+
* Supported formats:
|
|
71
|
+
* - "512m" or "512M" -> 536870912 (512 * 1024^2)
|
|
72
|
+
* - "2g" or "2G" -> 2147483648 (2 * 1024^3)
|
|
73
|
+
* - "1024k" or "1024K" -> 1048576 (1024 * 1024)
|
|
74
|
+
*
|
|
75
|
+
* @throws Error if the format is invalid
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseMemoryString(memory: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Validate a `ResourceRequest` literal (e.g., from compile-time SDK input).
|
|
80
|
+
*
|
|
81
|
+
* Checks:
|
|
82
|
+
* - `memory` strings parse via `parseMemoryString`.
|
|
83
|
+
* - `cpus` are positive numbers ≤ 256 (max practical scaler).
|
|
84
|
+
* - When both `requests` and `limits` are set on the same dimension,
|
|
85
|
+
* `requests <= limits` (a request that exceeds its own limit is nonsensical).
|
|
86
|
+
*
|
|
87
|
+
* Throws on the first violation with a descriptive error.
|
|
88
|
+
*/
|
|
89
|
+
export declare function validateResourceRequest(req: ResourceRequest): void;
|
|
90
|
+
//# sourceMappingURL=resource-types.d.ts.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/scaler/resource-types.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resource request and limit types for jobs and scalers.
|
|
6
|
+
*
|
|
7
|
+
* Single source of truth — re-exported from the engine barrel and consumed by:
|
|
8
|
+
* - SDK (`Job` / `JobOptions` `resources` field)
|
|
9
|
+
* - compiler (compile-time validation + lockfile emission)
|
|
10
|
+
* - orchestrator (scaler accounting + backend enforcement)
|
|
11
|
+
* - dashboard (read-only display)
|
|
12
|
+
*
|
|
13
|
+
* Shape is K8s-style requests/limits split:
|
|
14
|
+
* - `requests` drive the scheduler's cap math (per-scaler / per-orch / per-machine).
|
|
15
|
+
* - `limits` drive kernel-side enforcement (Docker memory + nanoCpus, FC memSizeMib + vcpuCount,
|
|
16
|
+
* optional bare-metal systemd-run scope).
|
|
17
|
+
*
|
|
18
|
+
* Mirroring rule (applied at the orchestrator's resolve step):
|
|
19
|
+
* - request-only ⇒ limit = request
|
|
20
|
+
* - limit-only ⇒ request = limit
|
|
21
|
+
* - neither ⇒ scaler default
|
|
22
|
+
* - nothing anywhere ⇒ 0/0 (job counts toward agent-count cap only)
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Zod schema for a single resource spec (cpus + memory).
|
|
26
|
+
*/
|
|
27
|
+
const resourceSpecSchema = z.object({
|
|
28
|
+
cpus: z.number().positive().max(256).optional(),
|
|
29
|
+
memory: z.string().optional()
|
|
30
|
+
}).strict();
|
|
31
|
+
/**
|
|
32
|
+
* Zod schema for the nested request/limit form.
|
|
33
|
+
*/
|
|
34
|
+
const resourceRequestNestedSchema = z.object({
|
|
35
|
+
requests: resourceSpecSchema.optional(),
|
|
36
|
+
limits: resourceSpecSchema.optional()
|
|
37
|
+
}).strict();
|
|
38
|
+
/**
|
|
39
|
+
* Memory string units supported across the codebase.
|
|
40
|
+
*
|
|
41
|
+
* Mirrors `parseMemoryString` in `packages/orchestrator/src/scaler/config.ts` —
|
|
42
|
+
* keep both in sync. Hoisted here so the compiler (browser-safe) can validate
|
|
43
|
+
* memory strings at compile time without depending on the orchestrator package.
|
|
44
|
+
*/
|
|
45
|
+
const MEMORY_FORMAT_RE = /^(\d+(?:\.\d+)?)\s*([kmgKMG])$/;
|
|
46
|
+
/**
|
|
47
|
+
* Parse a memory string with unit suffix to bytes.
|
|
48
|
+
*
|
|
49
|
+
* Supported formats:
|
|
50
|
+
* - "512m" or "512M" -> 536870912 (512 * 1024^2)
|
|
51
|
+
* - "2g" or "2G" -> 2147483648 (2 * 1024^3)
|
|
52
|
+
* - "1024k" or "1024K" -> 1048576 (1024 * 1024)
|
|
53
|
+
*
|
|
54
|
+
* @throws Error if the format is invalid
|
|
55
|
+
*/
|
|
56
|
+
function parseMemoryString(memory) {
|
|
57
|
+
const match = memory.match(MEMORY_FORMAT_RE);
|
|
58
|
+
if (!match) throw new Error(`Invalid memory format: "${memory}". Expected format like "512m", "2g", or "1024k".`);
|
|
59
|
+
const value = parseFloat(match[1]);
|
|
60
|
+
const unit = match[2].toLowerCase();
|
|
61
|
+
switch (unit) {
|
|
62
|
+
case "k": return Math.floor(value * 1024);
|
|
63
|
+
case "m": return Math.floor(value * 1024 * 1024);
|
|
64
|
+
case "g": return Math.floor(value * 1024 * 1024 * 1024);
|
|
65
|
+
default: throw new Error(`Unknown memory unit: "${unit}"`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validate a `ResourceRequest` literal (e.g., from compile-time SDK input).
|
|
70
|
+
*
|
|
71
|
+
* Checks:
|
|
72
|
+
* - `memory` strings parse via `parseMemoryString`.
|
|
73
|
+
* - `cpus` are positive numbers ≤ 256 (max practical scaler).
|
|
74
|
+
* - When both `requests` and `limits` are set on the same dimension,
|
|
75
|
+
* `requests <= limits` (a request that exceeds its own limit is nonsensical).
|
|
76
|
+
*
|
|
77
|
+
* Throws on the first violation with a descriptive error.
|
|
78
|
+
*/
|
|
79
|
+
function validateResourceRequest(req) {
|
|
80
|
+
resourceRequestNestedSchema.parse(req);
|
|
81
|
+
for (const side of ["requests", "limits"]) {
|
|
82
|
+
const spec = req[side];
|
|
83
|
+
if (!spec) continue;
|
|
84
|
+
if (spec.memory !== void 0) parseMemoryString(spec.memory);
|
|
85
|
+
if (spec.cpus !== void 0 && spec.cpus <= 0) throw new Error(`resources.${side}.cpus must be > 0 (got ${spec.cpus})`);
|
|
86
|
+
}
|
|
87
|
+
const requests = req.requests;
|
|
88
|
+
const limits = req.limits;
|
|
89
|
+
if (requests && limits) {
|
|
90
|
+
if (requests.cpus !== void 0 && limits.cpus !== void 0 && requests.cpus > limits.cpus) throw new Error(`resources.requests.cpus (${requests.cpus}) must not exceed resources.limits.cpus (${limits.cpus})`);
|
|
91
|
+
if (requests.memory !== void 0 && limits.memory !== void 0) {
|
|
92
|
+
if (parseMemoryString(requests.memory) > parseMemoryString(limits.memory)) throw new Error(`resources.requests.memory (${requests.memory}) must not exceed resources.limits.memory (${limits.memory})`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { parseMemoryString, resourceRequestNestedSchema, resourceSpecSchema, validateResourceRequest };
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=resource-types.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Scaler backend type identifiers.
|
|
4
|
+
*
|
|
5
|
+
* Enumerates the agent provisioning backends supported by the orchestrator's
|
|
6
|
+
* auto-scaler module. Each backend implements the ScalerBackend interface.
|
|
7
|
+
* Access values: ScalerBackendType.enum.container, ScalerBackendType.enum.firecracker, etc.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ScalerBackendType: z.ZodEnum<{
|
|
10
|
+
container: "container";
|
|
11
|
+
"bare-metal": "bare-metal";
|
|
12
|
+
firecracker: "firecracker";
|
|
13
|
+
kubernetes: "kubernetes";
|
|
14
|
+
}>;
|
|
15
|
+
export type ScalerBackendType = z.infer<typeof ScalerBackendType>;
|
|
16
|
+
//# sourceMappingURL=scaler-backend-type.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/scaler/scaler-backend-type.ts
|
|
4
|
+
/**
|
|
5
|
+
* Scaler backend type identifiers.
|
|
6
|
+
*
|
|
7
|
+
* Enumerates the agent provisioning backends supported by the orchestrator's
|
|
8
|
+
* auto-scaler module. Each backend implements the ScalerBackend interface.
|
|
9
|
+
* Access values: ScalerBackendType.enum.container, ScalerBackendType.enum.firecracker, etc.
|
|
10
|
+
*/
|
|
11
|
+
const ScalerBackendType = z.enum([
|
|
12
|
+
"container",
|
|
13
|
+
"bare-metal",
|
|
14
|
+
"firecracker",
|
|
15
|
+
"kubernetes"
|
|
16
|
+
]);
|
|
17
|
+
//#endregion
|
|
18
|
+
export { ScalerBackendType };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=scaler-backend-type.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets management module.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports scope-based secret store types and audit entry.
|
|
5
|
+
*/
|
|
6
|
+
export type { SecretStore, AuditEntry, BackendType, BackendHealthStatus, BackendDescriptor, AddBackendParams, BackendManager, BackendSyncManager, } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets management interfaces for KiCI.
|
|
3
|
+
*
|
|
4
|
+
* Defines the pluggable backend contract (SecretStore) and audit logging
|
|
5
|
+
* (AuditEntry) for the scoped secrets system.
|
|
6
|
+
*
|
|
7
|
+
* These interfaces are backend-agnostic -- implementations live in
|
|
8
|
+
* orchestrator (PG backend) or can be swapped for Vault, etc.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Scope-based secret store interface.
|
|
12
|
+
* Provides access to secrets organized by (orgId, scope, key).
|
|
13
|
+
*/
|
|
14
|
+
export interface SecretStore {
|
|
15
|
+
/** Get all secrets for a scope as decrypted key-value pairs. */
|
|
16
|
+
getSecrets(orgId: string, scope: string): Promise<Record<string, string>>;
|
|
17
|
+
/** Set (create or update) a secret in a scope. */
|
|
18
|
+
setSecret(orgId: string, scope: string, key: string, value: string): Promise<void>;
|
|
19
|
+
/** Delete a secret from a scope. */
|
|
20
|
+
deleteSecret(orgId: string, scope: string, key: string): Promise<void>;
|
|
21
|
+
/** List all secret key names in a scope (no values returned). */
|
|
22
|
+
listKeys(orgId: string, scope: string): Promise<string[]>;
|
|
23
|
+
/** List all distinct scopes for an org. */
|
|
24
|
+
listScopes(orgId: string): Promise<string[]>;
|
|
25
|
+
/** Create an empty scope (implementation may use a sentinel row or metadata table). */
|
|
26
|
+
createScope?(orgId: string, scope: string): Promise<void>;
|
|
27
|
+
/** Rename a scope -- update all secret rows from oldScope to newScope. */
|
|
28
|
+
renameScope?(orgId: string, oldScope: string, newScope: string): Promise<void>;
|
|
29
|
+
/** Delete a scope and all its secrets. */
|
|
30
|
+
deleteScope?(orgId: string, scope: string): Promise<void>;
|
|
31
|
+
/** Get all secrets for an org (for resolver). Returns encrypted values. */
|
|
32
|
+
getAllSecrets(orgId: string): Promise<Array<{
|
|
33
|
+
scope: string;
|
|
34
|
+
key: string;
|
|
35
|
+
encryptedValue: string;
|
|
36
|
+
keyVersion: number;
|
|
37
|
+
}>>;
|
|
38
|
+
}
|
|
39
|
+
/** Supported secret backend types. */
|
|
40
|
+
export type BackendType = 'pg' | 'vault';
|
|
41
|
+
/** Health status of a secret backend. */
|
|
42
|
+
export type BackendHealthStatus = 'healthy' | 'degraded' | 'unreachable' | 'unknown';
|
|
43
|
+
/**
|
|
44
|
+
* Metadata descriptor for a registered secret backend.
|
|
45
|
+
* Does NOT include credentials — safe to expose via API.
|
|
46
|
+
*/
|
|
47
|
+
export interface BackendDescriptor {
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
backendType: BackendType;
|
|
51
|
+
/** Comma-separated globs for scope filtering. Default '**'. */
|
|
52
|
+
scopeFilter: string;
|
|
53
|
+
/** Sync interval in milliseconds. Default 300000 (5 min). */
|
|
54
|
+
syncIntervalMs: number;
|
|
55
|
+
enabled: boolean;
|
|
56
|
+
healthStatus: BackendHealthStatus;
|
|
57
|
+
scopeCount: number;
|
|
58
|
+
lastSyncAt: Date | null;
|
|
59
|
+
lastSyncError: string | null;
|
|
60
|
+
lastHealthCheckAt: Date | null;
|
|
61
|
+
createdAt: Date;
|
|
62
|
+
updatedAt: Date;
|
|
63
|
+
}
|
|
64
|
+
/** Parameters for registering a new secret backend. */
|
|
65
|
+
export interface AddBackendParams {
|
|
66
|
+
name: string;
|
|
67
|
+
backendType: BackendType;
|
|
68
|
+
config: Record<string, unknown>;
|
|
69
|
+
scopeFilter?: string;
|
|
70
|
+
syncIntervalMs?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Backend lifecycle manager interface.
|
|
74
|
+
* Provides CRUD, health checks, and connection testing for secret backends.
|
|
75
|
+
*/
|
|
76
|
+
export interface BackendManager {
|
|
77
|
+
/** Check backend connectivity. Returns health status. */
|
|
78
|
+
checkHealth(name: string): Promise<BackendHealthStatus>;
|
|
79
|
+
/** Trigger scope discovery sync for a backend (or all if name omitted). */
|
|
80
|
+
syncScopes(name?: string): Promise<void>;
|
|
81
|
+
/** List all registered backends (no credentials). */
|
|
82
|
+
listBackends(): Promise<BackendDescriptor[]>;
|
|
83
|
+
/** Get a single backend by name. */
|
|
84
|
+
getBackend(name: string): Promise<BackendDescriptor | null>;
|
|
85
|
+
/** Register a new backend. Returns the descriptor. */
|
|
86
|
+
addBackend(params: AddBackendParams): Promise<BackendDescriptor>;
|
|
87
|
+
/** Remove a backend by name. Returns true if removed. */
|
|
88
|
+
removeBackend(name: string): Promise<boolean>;
|
|
89
|
+
/** Test connectivity without persisting. */
|
|
90
|
+
testConnection(params: AddBackendParams): Promise<{
|
|
91
|
+
ok: boolean;
|
|
92
|
+
error?: string;
|
|
93
|
+
latencyMs: number;
|
|
94
|
+
}>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Periodic scope sync manager for secret backends.
|
|
98
|
+
*/
|
|
99
|
+
export interface BackendSyncManager {
|
|
100
|
+
syncBackend(name: string): Promise<{
|
|
101
|
+
scopeCount: number;
|
|
102
|
+
error?: string;
|
|
103
|
+
}>;
|
|
104
|
+
syncAllBackends(): Promise<Array<{
|
|
105
|
+
name: string;
|
|
106
|
+
scopeCount: number;
|
|
107
|
+
error?: string;
|
|
108
|
+
}>>;
|
|
109
|
+
startPeriodicSync(): void;
|
|
110
|
+
stopPeriodicSync(): void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Audit log entry for secrets operations.
|
|
114
|
+
* Used for tracking access patterns and security events.
|
|
115
|
+
*/
|
|
116
|
+
export interface AuditEntry {
|
|
117
|
+
/** The action performed (e.g., 'getSecrets', 'setSecret', 'resolve'). */
|
|
118
|
+
action: string;
|
|
119
|
+
/** The scope or context name involved. */
|
|
120
|
+
contextName: string;
|
|
121
|
+
/** Routing key scope. */
|
|
122
|
+
routingKey: string | null;
|
|
123
|
+
/** Secret keys involved (null for scope-level ops). */
|
|
124
|
+
secretKeys: string[] | null;
|
|
125
|
+
/** Whether the operation was allowed or denied. */
|
|
126
|
+
outcome: 'allowed' | 'denied';
|
|
127
|
+
/** CI run ID if applicable. */
|
|
128
|
+
runId: string | null;
|
|
129
|
+
/** Job ID if applicable. */
|
|
130
|
+
jobId: string | null;
|
|
131
|
+
/** User ID if applicable. */
|
|
132
|
+
userId: string | null;
|
|
133
|
+
/** User role if applicable. */
|
|
134
|
+
role: string | null;
|
|
135
|
+
/** Additional metadata. */
|
|
136
|
+
metadata: Record<string, unknown> | null;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=types.d.ts.map
|