@capybara-hq/kernel 0.1.0-rc.26 → 0.1.0-rc.28
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/app.js +2 -0
- package/dist/catalog/catalog-content.d.ts +18 -1
- package/dist/catalog/catalog-content.js +5 -2
- package/dist/catalog/catalog-scope.service.js +3 -2
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/org-catalog.service.js +13 -3
- package/dist/catalog/plugin-install.d.ts +37 -16
- package/dist/catalog/plugin-install.js +108 -34
- package/dist/catalog/plugin-upgrade.js +1 -0
- package/dist/channels/actions.d.ts +4 -1
- package/dist/channels/actions.js +5 -2
- package/dist/channels/cards.d.ts +7 -1
- package/dist/channels/cards.js +28 -1
- package/dist/channels/phrases.d.ts +15 -0
- package/dist/channels/phrases.js +9 -0
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.js +69 -0
- package/dist/conversations/events.d.ts +14 -0
- package/dist/conversations/events.js +20 -0
- package/dist/db/kernel-schema.d.ts +19 -4
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +5 -0
- package/dist/git/gateway.d.ts +93 -0
- package/dist/git/gateway.js +750 -0
- package/dist/git/gateway.route.d.ts +16 -0
- package/dist/git/gateway.route.js +41 -0
- package/dist/git/git.module.d.ts +10 -0
- package/dist/git/git.module.js +31 -0
- package/dist/git/identity.d.ts +80 -0
- package/dist/git/identity.js +209 -0
- package/dist/git/pkt-line.d.ts +53 -0
- package/dist/git/pkt-line.js +146 -0
- package/dist/git/run-end.d.ts +29 -0
- package/dist/git/run-end.js +121 -0
- package/dist/git/sources.d.ts +42 -0
- package/dist/git/sources.js +134 -0
- package/dist/git/tickets.d.ts +69 -0
- package/dist/git/tickets.js +194 -0
- package/dist/http/api.module.js +3 -0
- package/dist/http/app.d.ts +6 -0
- package/dist/http/app.js +3 -0
- package/dist/infra/config/kernel-config.service.js +2 -0
- package/dist/orgs/settings.service.d.ts +21 -0
- package/dist/orgs/settings.service.js +18 -0
- package/dist/overrides.d.ts +6 -0
- package/dist/overrides.js +4 -0
- package/dist/platform/exclusions.js +3 -0
- package/dist/runtime/run-finish.d.ts +5 -0
- package/dist/runtime/run-finish.js +12 -3
- package/dist/runtime/runtime.module.js +2 -0
- package/dist/runtime/waits.js +7 -5
- package/dist/schedules/fire.d.ts +3 -3
- package/dist/schedules/fire.js +7 -4
- package/dist/schedules/grant-rules.d.ts +40 -0
- package/dist/schedules/grant-rules.js +83 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +9 -7
- package/dist/schedules/scheduled-tasks.service.js +50 -15
- package/dist/schedules/types.d.ts +2 -0
- package/dist/tools/approvals.service.d.ts +100 -19
- package/dist/tools/approvals.service.js +288 -21
- package/dist/tools/builtin-names.d.ts +4 -2
- package/dist/tools/builtin-names.js +6 -1
- package/dist/tools/builtins/schedules.d.ts +11 -9
- package/dist/tools/builtins/schedules.js +202 -44
- package/dist/tools/connector-account-policies.d.ts +8 -0
- package/dist/tools/connector-account-policies.js +8 -0
- package/dist/tools/connectors.controller.d.ts +2 -0
- package/dist/tools/connectors.controller.js +5 -1
- package/dist/tools/connectors.service.d.ts +46 -3
- package/dist/tools/connectors.service.js +98 -9
- package/dist/tools/credentials.d.ts +18 -0
- package/dist/tools/credentials.js +60 -0
- package/dist/tools/credentials.module.d.ts +7 -0
- package/dist/tools/credentials.module.js +22 -0
- package/dist/tools/git-asks.d.ts +113 -0
- package/dist/tools/git-asks.js +174 -0
- package/dist/tools/git-push-policy.d.ts +89 -0
- package/dist/tools/git-push-policy.js +175 -0
- package/dist/tools/info.d.ts +3 -3
- package/dist/tools/info.js +3 -3
- package/dist/tools/network-asks.d.ts +5 -0
- package/dist/tools/network-asks.js +9 -2
- package/dist/tools/tools.module.js +4 -3
- package/package.json +3 -3
- package/src/migrations/0126_git_gateway.sql +10 -0
- package/src/migrations/0127_git_push_policy.sql +12 -0
- package/src/migrations/0128_scheduled_task_plugin_disabled.sql +10 -0
- package/src/migrations/0129_connector_plugin_disabled.sql +5 -0
package/dist/channels/phrases.js
CHANGED
|
@@ -96,6 +96,15 @@ export const CHANNEL_PHRASES = {
|
|
|
96
96
|
networkAllowOnce: { zh: "这次允许", en: "Allow this time" },
|
|
97
97
|
/** A network ask's 「always」 button. */
|
|
98
98
|
networkAllowAlways: { zh: "这台设备一直允许", en: "Always allow on this device" },
|
|
99
|
+
/** A git push ask's card title (`{repo}`; sandbox git credentials spec §7). */
|
|
100
|
+
gitTitle: {
|
|
101
|
+
zh: "智能体想推送到 {repo},允许吗?",
|
|
102
|
+
en: "The agent wants to push to {repo}. Allow?",
|
|
103
|
+
},
|
|
104
|
+
/** A git push ask's 「once」 button. */
|
|
105
|
+
gitAllowOnce: { zh: "这次允许", en: "Allow this time" },
|
|
106
|
+
/** A git push ask's 「always」 button: the person's standing allow for the repository. */
|
|
107
|
+
gitAllowAlways: { zh: "这个仓库一直允许", en: "Always allow this repository" },
|
|
99
108
|
/** 提问卡片的随附文本。 */
|
|
100
109
|
questionTitle: { zh: "需要你的回答", en: "Your input is needed" },
|
|
101
110
|
/** 连接卡片的随附文本。 */
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -144,6 +144,14 @@ export declare const KernelConfigSchema: z.ZodObject<{
|
|
|
144
144
|
driftIntervalHours: z.ZodDefault<z.ZodNumber>;
|
|
145
145
|
maxResultReadChars: z.ZodDefault<z.ZodNumber>;
|
|
146
146
|
oauthAllowInsecureLoopback: z.ZodDefault<z.ZodBoolean>;
|
|
147
|
+
git: z.ZodPrefault<z.ZodObject<{
|
|
148
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
149
|
+
gatewayUrl: z.ZodOptional<z.ZodURL>;
|
|
150
|
+
maxBytesPerRun: z.ZodDefault<z.ZodNumber>;
|
|
151
|
+
idleTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
152
|
+
maxConcurrentPerOrg: z.ZodDefault<z.ZodNumber>;
|
|
153
|
+
ticketTtlSeconds: z.ZodDefault<z.ZodNumber>;
|
|
154
|
+
}, z.core.$strip>>;
|
|
147
155
|
}, z.core.$strip>>;
|
|
148
156
|
channels: z.ZodDefault<z.ZodObject<{
|
|
149
157
|
leaseTtlMs: z.ZodDefault<z.ZodNumber>;
|
package/dist/config/schema.js
CHANGED
|
@@ -773,6 +773,68 @@ export const KernelConfigSchema = z.object({
|
|
|
773
773
|
.meta(meta({
|
|
774
774
|
description: "Allow OAuth discovery, registration and token endpoints over plain http on loopback hosts (development and tests only; production requires https)",
|
|
775
775
|
})),
|
|
776
|
+
git: z
|
|
777
|
+
.object({
|
|
778
|
+
enabled: z
|
|
779
|
+
.boolean()
|
|
780
|
+
.default(true)
|
|
781
|
+
.meta(meta({
|
|
782
|
+
hot: true,
|
|
783
|
+
description: "Serve the git gateway that lets sandboxes clone and push over HTTPS with run tickets; when off the gateway refuses every request",
|
|
784
|
+
})),
|
|
785
|
+
gatewayUrl: z
|
|
786
|
+
.url({ protocol: /^https?$/ })
|
|
787
|
+
.refine((u) => {
|
|
788
|
+
const x = URL.canParse(u) ? new URL(u) : null;
|
|
789
|
+
return (x !== null &&
|
|
790
|
+
x.pathname === "/" &&
|
|
791
|
+
!x.search &&
|
|
792
|
+
!x.hash &&
|
|
793
|
+
!x.username &&
|
|
794
|
+
!x.password);
|
|
795
|
+
}, { message: "must be an origin: no path, query, fragment or credentials" })
|
|
796
|
+
.optional()
|
|
797
|
+
.meta(meta({
|
|
798
|
+
description: "Origin (http or https, no path, query or credentials) of the kernel as sandboxes reach it, e.g. https://kernel.internal:8080; when unset the kernel uses http.publicUrl",
|
|
799
|
+
})),
|
|
800
|
+
maxBytesPerRun: z
|
|
801
|
+
.number()
|
|
802
|
+
.int()
|
|
803
|
+
.min(1048576)
|
|
804
|
+
.max(107374182400)
|
|
805
|
+
.default(5368709120)
|
|
806
|
+
.meta(meta({
|
|
807
|
+
description: "Maximum bytes the git gateway transfers (both directions) for one run, between 1 MiB and 100 GiB (default 5 GiB)",
|
|
808
|
+
})),
|
|
809
|
+
idleTimeoutMs: z
|
|
810
|
+
.number()
|
|
811
|
+
.int()
|
|
812
|
+
.min(1000)
|
|
813
|
+
.max(3600000)
|
|
814
|
+
.default(60000)
|
|
815
|
+
.meta(meta({
|
|
816
|
+
description: "A git gateway request that moves no data for this many milliseconds is aborted, between 1000 and 3600000",
|
|
817
|
+
})),
|
|
818
|
+
maxConcurrentPerOrg: z
|
|
819
|
+
.number()
|
|
820
|
+
.int()
|
|
821
|
+
.min(1)
|
|
822
|
+
.max(1000)
|
|
823
|
+
.default(8)
|
|
824
|
+
.meta(meta({
|
|
825
|
+
description: "Maximum git gateway requests in flight at once for one org, between 1 and 1000",
|
|
826
|
+
})),
|
|
827
|
+
ticketTtlSeconds: z
|
|
828
|
+
.number()
|
|
829
|
+
.int()
|
|
830
|
+
.min(60)
|
|
831
|
+
.max(86400)
|
|
832
|
+
.default(900)
|
|
833
|
+
.meta(meta({
|
|
834
|
+
description: "Lifetime in seconds of the ticket issued for one exec to the git gateway (a ticket also dies when its run ends), between 60 and 86400",
|
|
835
|
+
})),
|
|
836
|
+
})
|
|
837
|
+
.prefault({}),
|
|
776
838
|
})
|
|
777
839
|
.default({
|
|
778
840
|
timeoutMs: 60000,
|
|
@@ -787,6 +849,13 @@ export const KernelConfigSchema = z.object({
|
|
|
787
849
|
driftIntervalHours: 24,
|
|
788
850
|
maxResultReadChars: 20000,
|
|
789
851
|
oauthAllowInsecureLoopback: false,
|
|
852
|
+
git: {
|
|
853
|
+
enabled: true,
|
|
854
|
+
maxBytesPerRun: 5368709120,
|
|
855
|
+
idleTimeoutMs: 60000,
|
|
856
|
+
maxConcurrentPerOrg: 8,
|
|
857
|
+
ticketTtlSeconds: 900,
|
|
858
|
+
},
|
|
790
859
|
}),
|
|
791
860
|
channels: z
|
|
792
861
|
.object({
|
|
@@ -4,6 +4,15 @@ import { z } from "zod";
|
|
|
4
4
|
export declare const NETWORK_ASK_MAX_HOSTS = 20;
|
|
5
5
|
/** The longest host name a network ask or `network_blocked` event carries. */
|
|
6
6
|
export declare const NETWORK_HOST_MAX_CHARS = 255;
|
|
7
|
+
/** The most refs one git push ask (and its `approval_requested.git`) lists. */
|
|
8
|
+
export declare const GIT_ASK_MAX_REFS = 20;
|
|
9
|
+
/** The longest ref name a git push ask carries. */
|
|
10
|
+
export declare const GIT_REF_MAX_CHARS = 255;
|
|
11
|
+
/**
|
|
12
|
+
* The longest `<owner>/<repo>` a git push ask carries (GitHub allows 39 + 100 characters): the
|
|
13
|
+
* grant key `git:push:<owner>/<repo>` must fit an org's `forbiddenTools` entry (200 characters).
|
|
14
|
+
*/
|
|
15
|
+
export declare const GIT_REPO_MAX_CHARS = 191;
|
|
7
16
|
/** The longest deny reason (characters): the decision route's limit and `approval_decided.reason`'s. */
|
|
8
17
|
export declare const APPROVAL_DENY_REASON_MAX_CHARS = 500;
|
|
9
18
|
/** 一条 `media_excluded` 事件最多的附件数。 */
|
|
@@ -716,6 +725,11 @@ export declare const ConversationEventSchema: z.ZodDiscriminatedUnion<[z.ZodObje
|
|
|
716
725
|
network: z.ZodOptional<z.ZodObject<{
|
|
717
726
|
hosts: z.ZodArray<z.ZodString>;
|
|
718
727
|
}, z.core.$strip>>;
|
|
728
|
+
git: z.ZodOptional<z.ZodObject<{
|
|
729
|
+
host: z.ZodString;
|
|
730
|
+
repo: z.ZodString;
|
|
731
|
+
refs: z.ZodArray<z.ZodString>;
|
|
732
|
+
}, z.core.$strip>>;
|
|
719
733
|
}, z.core.$strip>;
|
|
720
734
|
}, z.core.$strip>, z.ZodObject<{
|
|
721
735
|
type: z.ZodLiteral<"approval_decided">;
|
|
@@ -31,6 +31,15 @@ const ApproverFields = {
|
|
|
31
31
|
export const NETWORK_ASK_MAX_HOSTS = 20;
|
|
32
32
|
/** The longest host name a network ask or `network_blocked` event carries. */
|
|
33
33
|
export const NETWORK_HOST_MAX_CHARS = 255;
|
|
34
|
+
/** The most refs one git push ask (and its `approval_requested.git`) lists. */
|
|
35
|
+
export const GIT_ASK_MAX_REFS = 20;
|
|
36
|
+
/** The longest ref name a git push ask carries. */
|
|
37
|
+
export const GIT_REF_MAX_CHARS = 255;
|
|
38
|
+
/**
|
|
39
|
+
* The longest `<owner>/<repo>` a git push ask carries (GitHub allows 39 + 100 characters): the
|
|
40
|
+
* grant key `git:push:<owner>/<repo>` must fit an org's `forbiddenTools` entry (200 characters).
|
|
41
|
+
*/
|
|
42
|
+
export const GIT_REPO_MAX_CHARS = 191;
|
|
34
43
|
/** The longest deny reason (characters): the decision route's limit and `approval_decided.reason`'s. */
|
|
35
44
|
export const APPROVAL_DENY_REASON_MAX_CHARS = 500;
|
|
36
45
|
/** 一条 `media_excluded` 事件最多的附件数。 */
|
|
@@ -604,6 +613,17 @@ export const ConversationEventSchema = z.discriminatedUnion("type", [
|
|
|
604
613
|
.max(NETWORK_ASK_MAX_HOSTS),
|
|
605
614
|
})
|
|
606
615
|
.optional(),
|
|
616
|
+
/**
|
|
617
|
+
* A git push ask (sandbox git credentials spec §7): the host, repository and refs the push
|
|
618
|
+
* the gateway held would have updated. Display only, never model-visible, as `network`.
|
|
619
|
+
*/
|
|
620
|
+
git: z
|
|
621
|
+
.object({
|
|
622
|
+
host: z.string().min(1).max(NETWORK_HOST_MAX_CHARS),
|
|
623
|
+
repo: z.string().min(1).max(GIT_REPO_MAX_CHARS),
|
|
624
|
+
refs: z.array(z.string().min(1).max(GIT_REF_MAX_CHARS)).max(GIT_ASK_MAX_REFS),
|
|
625
|
+
})
|
|
626
|
+
.optional(),
|
|
607
627
|
...ApproverFields,
|
|
608
628
|
})),
|
|
609
629
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConversationSource, FileSystemHandle, ParsedTheme, SandboxTier, SkillInvocation } from "@capybara-hq/plugin-sdk";
|
|
1
|
+
import type { ConversationSource, FileSystemHandle, GitHostEntry, ParsedTheme, SandboxTier, SkillInvocation } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { ColumnType, Generated, Kysely } from "kysely";
|
|
3
3
|
import type { ModelRef } from "../agents/definition.js";
|
|
4
4
|
import type { ScheduleChat, ScheduleMarker, ScheduleMode, SchedulePauseReason, ScheduleStatus, ScheduleTrigger, TaskRunSkipReason, TaskRunStatus } from "../schedules/types.js";
|
|
@@ -454,6 +454,18 @@ export interface ConnectorsTable {
|
|
|
454
454
|
* hash, mode: null }`); null when unknown (custom connectors, connectors before 0106).
|
|
455
455
|
*/
|
|
456
456
|
guide_ack: ColumnType<GuideAckJson | null, string | null | undefined, string | null>;
|
|
457
|
+
/** 0126: the git hosts this connector declares (null: none). */
|
|
458
|
+
git_hosts: ColumnType<GitHostEntry[] | null, string | null | undefined, string | null>;
|
|
459
|
+
/** 0126: an org-owned connector serves as a git gateway source (personal ones always do). */
|
|
460
|
+
use_for_git: Generated<boolean>;
|
|
461
|
+
/** 0127: the org's policy for pushes through this connector (virtual tool `git_push`). */
|
|
462
|
+
git_push_policy: Generated<"allow" | "ask" | "deny">;
|
|
463
|
+
/**
|
|
464
|
+
* 0129: the plugin (catalog item) whose switch-off disabled this connector; null = not switched
|
|
465
|
+
* off by a plugin (an org admin's own disable, or enabled). Switching that plugin back on
|
|
466
|
+
* re-enables exactly the connectors it disabled.
|
|
467
|
+
*/
|
|
468
|
+
disabled_by_plugin_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
457
469
|
}
|
|
458
470
|
/**
|
|
459
471
|
* 0104: a member's own policy for one tool of a personal-credential connector, for calls made with
|
|
@@ -539,9 +551,12 @@ export interface ApprovalsTable {
|
|
|
539
551
|
} | null, string | null | undefined, string | null>;
|
|
540
552
|
/** 0086: the scopes the person may choose (null: derived, see `approvals.service.ts`). */
|
|
541
553
|
scopes: ColumnType<("once" | "session" | "always")[] | null, ("once" | "session" | "always")[] | null | undefined, ("once" | "session" | "always")[] | null>;
|
|
542
|
-
/**
|
|
543
|
-
|
|
544
|
-
|
|
554
|
+
/**
|
|
555
|
+
* 0114: what is asked: a tool call ('tool') or a refused network domain ('network'); 0126: a
|
|
556
|
+
* git push the gateway held ('git').
|
|
557
|
+
*/
|
|
558
|
+
kind: Generated<"tool" | "network" | "git">;
|
|
559
|
+
/** 0114: a network or git ask's facts, kept result and outcome (null for tool approvals). */
|
|
545
560
|
detail: ColumnType<unknown | null, string | null | undefined, string | null>;
|
|
546
561
|
}
|
|
547
562
|
/** 0010_tools.sql:AskUserQuestion 提问。 */
|
package/dist/errors.d.ts
CHANGED
|
@@ -191,6 +191,11 @@ export declare const ERROR_CODES: {
|
|
|
191
191
|
readonly "catalog.marketplace_browse_disabled": 409;
|
|
192
192
|
readonly "catalog.custom_disabled": 403;
|
|
193
193
|
readonly "catalog.not_deployed": 409;
|
|
194
|
+
/**
|
|
195
|
+
* The connector an install planned to reuse (a template it asked no input for) was removed before
|
|
196
|
+
* the install ran: retry it, so the new plan asks for the input.
|
|
197
|
+
*/
|
|
198
|
+
readonly "catalog.connector_removed": 409;
|
|
194
199
|
readonly "catalog.icon_not_found": 404;
|
|
195
200
|
readonly "catalog.guide_not_found": 404;
|
|
196
201
|
/** The check is not in the setup guide rendered for that mode and audience (setup guides v2 §10.3). */
|
package/dist/errors.js
CHANGED
|
@@ -191,6 +191,11 @@ export const ERROR_CODES = {
|
|
|
191
191
|
"catalog.marketplace_browse_disabled": 409,
|
|
192
192
|
"catalog.custom_disabled": 403,
|
|
193
193
|
"catalog.not_deployed": 409,
|
|
194
|
+
/**
|
|
195
|
+
* The connector an install planned to reuse (a template it asked no input for) was removed before
|
|
196
|
+
* the install ran: retry it, so the new plan asks for the input.
|
|
197
|
+
*/
|
|
198
|
+
"catalog.connector_removed": 409,
|
|
194
199
|
"catalog.icon_not_found": 404,
|
|
195
200
|
"catalog.guide_not_found": 404,
|
|
196
201
|
/** The check is not in the setup guide rendered for that mode and audience (setup guides v2 §10.3). */
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from "fastify";
|
|
2
|
+
import type { Redis } from "ioredis";
|
|
3
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
4
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
5
|
+
import type { KernelLogger } from "../log.js";
|
|
6
|
+
import { Credentials } from "../tools/credentials.js";
|
|
7
|
+
import { GitSources } from "./sources.js";
|
|
8
|
+
import { GitTickets } from "./tickets.js";
|
|
9
|
+
/**
|
|
10
|
+
* The git gateway (sandbox git credentials spec §5): relays git smart-HTTP from a sandbox to a git
|
|
11
|
+
* host, authenticated by a run ticket, adding the actor's credential on the way out. Stateless
|
|
12
|
+
* across replicas: the ticket, the source, the push policy, the byte and concurrency counters are
|
|
13
|
+
* read from Redis / PG on every request; only the request's own idle timer lives in the process.
|
|
14
|
+
*
|
|
15
|
+
* The route (`/git/v1/<host>/<owner>/<repo>[.git]/<endpoint>`, {@link GIT_GATEWAY_PREFIX}) is a raw
|
|
16
|
+
* Fastify route (`gateway.route.ts`), like the channel webhook: git sends no CSRF header and the
|
|
17
|
+
* ticket is not an API credential, so neither the `AuthGuard` nor the API's error envelope apply.
|
|
18
|
+
* Everything git shows is plain text or pkt-lines in English.
|
|
19
|
+
*/
|
|
20
|
+
/** The route prefix. */
|
|
21
|
+
export declare const GIT_GATEWAY_PREFIX = "/git/v1/";
|
|
22
|
+
/** The smart-HTTP services. */
|
|
23
|
+
export type GitService = "git-upload-pack" | "git-receive-pack";
|
|
24
|
+
/** A parsed gateway path. */
|
|
25
|
+
export interface GitGatewayTarget {
|
|
26
|
+
host: string;
|
|
27
|
+
/** `<owner>/<repo>` as written (validated), for the upstream URL. */
|
|
28
|
+
path: string;
|
|
29
|
+
/** `<owner>/<repo>` normalized (lower case, no `.git`), for policy and allowlists. */
|
|
30
|
+
repo: string;
|
|
31
|
+
/** `info/refs` (GET, with `service`) or the service endpoint itself (POST). */
|
|
32
|
+
endpoint: "info/refs" | GitService;
|
|
33
|
+
service: GitService;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Test seam (`KernelAppOptions.overrides`): the upstream origin of a git host (default
|
|
37
|
+
* `https://<host>`), e.g. a loopback fake for `github.com`. Production validation is unchanged:
|
|
38
|
+
* the fake is reached through the same `safeFetch` rules (loopback http only under
|
|
39
|
+
* `tools.oauthAllowInsecureLoopback`).
|
|
40
|
+
*/
|
|
41
|
+
export declare const GIT_UPSTREAM_ORIGIN: unique symbol;
|
|
42
|
+
export type GitUpstreamOrigin = (host: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Parses `/git/v1/<host>/<owner>/<repo>[.git]/<endpoint>` with its query: GET `info/refs` with
|
|
45
|
+
* `service=git-upload-pack|git-receive-pack` and nothing else in the query, or POST
|
|
46
|
+
* `git-upload-pack` / `git-receive-pack` without a query. Anything else (dumb HTTP, other paths,
|
|
47
|
+
* other methods) is null (404).
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseGitGatewayPath(method: string, url: string): GitGatewayTarget | null;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the ticket's repository allowlist admits `repo` (normalized). Entries are
|
|
52
|
+
* `<owner>/<repo>`, `<owner>/*` or `*`, compared case-insensitively; no list admits every one.
|
|
53
|
+
*/
|
|
54
|
+
export declare function repoAllowed(repos: readonly string[] | undefined, repo: string): boolean;
|
|
55
|
+
/** The Redis counter of a run's relayed bytes. */
|
|
56
|
+
export declare const gitBytesKey: (runId: string) => string;
|
|
57
|
+
/** The Redis counter of an org's open gateway requests. */
|
|
58
|
+
export declare const gitConcurrencyKey: (orgId: string) => string;
|
|
59
|
+
export declare class GitGateway {
|
|
60
|
+
private readonly tickets;
|
|
61
|
+
private readonly sources;
|
|
62
|
+
private readonly credentials;
|
|
63
|
+
private readonly db;
|
|
64
|
+
private readonly redis;
|
|
65
|
+
/** Read per request: `tools.git.*` is read live. */
|
|
66
|
+
private readonly config;
|
|
67
|
+
private readonly log;
|
|
68
|
+
private readonly upstreamOrigin?;
|
|
69
|
+
constructor(tickets: Pick<GitTickets, "resolve">, sources: Pick<GitSources, "sourcesFor">, credentials: Pick<Credentials, "gitAuthorization" | "gitUnauthorized">, db: KernelDb, redis: Redis,
|
|
70
|
+
/** Read per request: `tools.git.*` is read live. */
|
|
71
|
+
config: Pick<KernelConfigService, "get">, log: Pick<KernelLogger, "info" | "warn" | "debug">, upstreamOrigin?: GitUpstreamOrigin | undefined);
|
|
72
|
+
/** Handles one gateway request (the raw route's handler). */
|
|
73
|
+
handle(req: FastifyRequest, reply: FastifyReply): Promise<void>;
|
|
74
|
+
/** The `git.push` audit row of a receive-pack and the run's fetch counters (best effort). */
|
|
75
|
+
private afterRequest;
|
|
76
|
+
/**
|
|
77
|
+
* Takes one of the org's gateway slots (Redis `git-conc:<orgId>`, TTL refreshed by every
|
|
78
|
+
* request and every byte meter flush) and returns how many are in use now with the slot's
|
|
79
|
+
* release (idempotent; a counter that went below zero after an expiry is reset).
|
|
80
|
+
*/
|
|
81
|
+
private acquireOrgSlot;
|
|
82
|
+
private done;
|
|
83
|
+
private relay;
|
|
84
|
+
/** The push decision for this target (spec §7). */
|
|
85
|
+
private decide;
|
|
86
|
+
/**
|
|
87
|
+
* Records a refused push for the exec (`git-ask:<execId>`, read by the Bash pipeline after the
|
|
88
|
+
* command) and, for an unattended run without a task grant, the missing grant on the task run.
|
|
89
|
+
*/
|
|
90
|
+
private recordRefusal;
|
|
91
|
+
/** The connector's auth (it may have changed since the source was chosen); null when gone. */
|
|
92
|
+
private connectorAuth;
|
|
93
|
+
}
|