@ipul-labs/forge 1.22.0 → 1.35.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/LICENSE +21 -0
- package/README.md +153 -78
- package/dist/apple-touch-icon.png +0 -0
- package/dist/assets/index-BmEuPeOG.js +27 -0
- package/dist/assets/index-CSH1OQYQ.css +1 -0
- package/dist/boot-check.js +98 -0
- package/dist/favicon.svg +8 -0
- package/dist/icon-192.png +0 -0
- package/dist/icon-512.png +0 -0
- package/dist/icon.svg +12 -0
- package/dist/index.html +33 -0
- package/dist/manifest.webmanifest +18 -0
- package/dist/theme-init.js +11 -0
- package/lib/bin/cli/analyze.d.ts.map +1 -1
- package/lib/bin/cli/analyze.js +3 -44
- package/lib/bin/cli/analyze.js.map +1 -1
- package/lib/bin/cli/apply.d.ts.map +1 -1
- package/lib/bin/cli/apply.js +2 -20
- package/lib/bin/cli/apply.js.map +1 -1
- package/lib/bin/cli/cifix.d.ts.map +1 -1
- package/lib/bin/cli/cifix.js +4 -28
- package/lib/bin/cli/cifix.js.map +1 -1
- package/lib/bin/cli/close.d.ts.map +1 -1
- package/lib/bin/cli/close.js +2 -33
- package/lib/bin/cli/close.js.map +1 -1
- package/lib/bin/cli/createIssue.d.ts.map +1 -1
- package/lib/bin/cli/createIssue.js +3 -12
- package/lib/bin/cli/createIssue.js.map +1 -1
- package/lib/bin/cli/doctor.d.ts.map +1 -1
- package/lib/bin/cli/doctor.js +3 -4
- package/lib/bin/cli/doctor.js.map +1 -1
- package/lib/bin/cli/init.js +1 -10
- package/lib/bin/cli/init.js.map +1 -1
- package/lib/bin/cli/issue.d.ts.map +1 -1
- package/lib/bin/cli/issue.js +3 -12
- package/lib/bin/cli/issue.js.map +1 -1
- package/lib/bin/cli/issues.d.ts.map +1 -1
- package/lib/bin/cli/issues.js +3 -12
- package/lib/bin/cli/issues.js.map +1 -1
- package/lib/bin/cli/merge.d.ts.map +1 -1
- package/lib/bin/cli/merge.js +4 -20
- package/lib/bin/cli/merge.js.map +1 -1
- package/lib/bin/cli/refine.d.ts.map +1 -1
- package/lib/bin/cli/refine.js +2 -26
- package/lib/bin/cli/refine.js.map +1 -1
- package/lib/bin/cli/repl.d.ts.map +1 -1
- package/lib/bin/cli/repl.js +4 -13
- package/lib/bin/cli/repl.js.map +1 -1
- package/lib/bin/cli/repos.d.ts.map +1 -1
- package/lib/bin/cli/repos.js +1 -11
- package/lib/bin/cli/repos.js.map +1 -1
- package/lib/bin/cli/resetPassword.d.ts +21 -0
- package/lib/bin/cli/resetPassword.d.ts.map +1 -0
- package/lib/bin/cli/resetPassword.js +69 -0
- package/lib/bin/cli/resetPassword.js.map +1 -0
- package/lib/bin/cli/resolution.d.ts.map +1 -1
- package/lib/bin/cli/resolution.js +2 -19
- package/lib/bin/cli/resolution.js.map +1 -1
- package/lib/bin/cli/serverClient.d.ts +2 -0
- package/lib/bin/cli/serverClient.d.ts.map +1 -1
- package/lib/bin/cli/serverClient.js +8 -4
- package/lib/bin/cli/serverClient.js.map +1 -1
- package/lib/bin/cli/session.d.ts.map +1 -1
- package/lib/bin/cli/session.js.map +1 -1
- package/lib/bin/cli/sessionStore.d.ts +1 -1
- package/lib/bin/cli/sessionStore.js +2 -2
- package/lib/bin/cli/sessionStore.js.map +1 -1
- package/lib/bin/cli/ship.d.ts.map +1 -1
- package/lib/bin/cli/ship.js +15 -23
- package/lib/bin/cli/ship.js.map +1 -1
- package/lib/bin/cli/update.d.ts.map +1 -1
- package/lib/bin/cli/update.js +34 -28
- package/lib/bin/cli/update.js.map +1 -1
- package/lib/bin/cli/updatePlan.d.ts +30 -0
- package/lib/bin/cli/updatePlan.d.ts.map +1 -0
- package/lib/bin/cli/updatePlan.js +50 -0
- package/lib/bin/cli/updatePlan.js.map +1 -0
- package/lib/bin/cli/utils.d.ts +3 -0
- package/lib/bin/cli/utils.d.ts.map +1 -1
- package/lib/bin/cli/utils.js +7 -23
- package/lib/bin/cli/utils.js.map +1 -1
- package/lib/bin/cli/validate.d.ts.map +1 -1
- package/lib/bin/cli/validate.js +3 -25
- package/lib/bin/cli/validate.js.map +1 -1
- package/lib/bin/cli/watch.d.ts.map +1 -1
- package/lib/bin/cli/watch.js +3 -12
- package/lib/bin/cli/watch.js.map +1 -1
- package/lib/bin/forge-agent.js +10 -22
- package/lib/bin/forge-agent.js.map +1 -1
- package/lib/server/app.d.ts +24 -0
- package/lib/server/app.d.ts.map +1 -0
- package/lib/server/app.js +58 -0
- package/lib/server/app.js.map +1 -0
- package/lib/server/forge/analyses/analysisStore.d.ts +53 -0
- package/lib/server/forge/analyses/analysisStore.d.ts.map +1 -0
- package/lib/server/forge/analyses/analysisStore.js +77 -0
- package/lib/server/forge/analyses/analysisStore.js.map +1 -0
- package/lib/server/forge/auth/apiTokens.d.ts +34 -0
- package/lib/server/forge/auth/apiTokens.d.ts.map +1 -0
- package/lib/server/forge/auth/apiTokens.js +44 -0
- package/lib/server/forge/auth/apiTokens.js.map +1 -0
- package/lib/server/forge/auth/auditLog.d.ts +36 -0
- package/lib/server/forge/auth/auditLog.d.ts.map +1 -0
- package/lib/server/forge/auth/auditLog.js +56 -0
- package/lib/server/forge/auth/auditLog.js.map +1 -0
- package/lib/server/forge/auth/authConfig.d.ts +13 -0
- package/lib/server/forge/auth/authConfig.d.ts.map +1 -0
- package/lib/server/forge/auth/authConfig.js +37 -0
- package/lib/server/forge/auth/authConfig.js.map +1 -0
- package/lib/server/forge/auth/createAuth.d.ts +130 -0
- package/lib/server/forge/auth/createAuth.d.ts.map +1 -0
- package/lib/server/forge/auth/createAuth.js +387 -0
- package/lib/server/forge/auth/createAuth.js.map +1 -0
- package/lib/server/forge/auth/middleware.d.ts +10 -0
- package/lib/server/forge/auth/middleware.d.ts.map +1 -0
- package/lib/server/forge/auth/middleware.js +22 -0
- package/lib/server/forge/auth/middleware.js.map +1 -0
- package/lib/server/forge/auth/oidc.d.ts +38 -0
- package/lib/server/forge/auth/oidc.d.ts.map +1 -0
- package/lib/server/forge/auth/oidc.js +63 -0
- package/lib/server/forge/auth/oidc.js.map +1 -0
- package/lib/server/forge/auth/passwords.d.ts +7 -0
- package/lib/server/forge/auth/passwords.d.ts.map +1 -0
- package/lib/server/forge/auth/passwords.js +28 -0
- package/lib/server/forge/auth/passwords.js.map +1 -0
- package/lib/server/forge/auth/resetPassword.d.ts +14 -0
- package/lib/server/forge/auth/resetPassword.d.ts.map +1 -0
- package/lib/server/forge/auth/resetPassword.js +29 -0
- package/lib/server/forge/auth/resetPassword.js.map +1 -0
- package/lib/server/forge/auth/roles.d.ts +7 -0
- package/lib/server/forge/auth/roles.d.ts.map +1 -0
- package/lib/server/forge/auth/roles.js +15 -0
- package/lib/server/forge/auth/roles.js.map +1 -0
- package/lib/server/forge/auth/sessions.d.ts +27 -0
- package/lib/server/forge/auth/sessions.d.ts.map +1 -0
- package/lib/server/forge/auth/sessions.js +37 -0
- package/lib/server/forge/auth/sessions.js.map +1 -0
- package/lib/server/forge/auth/testHarness.d.ts +104 -0
- package/lib/server/forge/auth/testHarness.d.ts.map +1 -0
- package/lib/server/forge/auth/testHarness.js +53 -0
- package/lib/server/forge/auth/testHarness.js.map +1 -0
- package/lib/server/forge/auth/tokenHash.d.ts +3 -0
- package/lib/server/forge/auth/tokenHash.d.ts.map +1 -0
- package/lib/server/forge/auth/tokenHash.js +4 -0
- package/lib/server/forge/auth/tokenHash.js.map +1 -0
- package/lib/server/forge/auth/users.d.ts +51 -0
- package/lib/server/forge/auth/users.d.ts.map +1 -0
- package/lib/server/forge/auth/users.js +118 -0
- package/lib/server/forge/auth/users.js.map +1 -0
- package/lib/server/forge/core/ForgeAgent.d.ts +43 -1
- package/lib/server/forge/core/ForgeAgent.d.ts.map +1 -1
- package/lib/server/forge/core/ForgeAgent.js +209 -61
- package/lib/server/forge/core/ForgeAgent.js.map +1 -1
- package/lib/server/forge/core/agentClient.d.ts +7 -23
- package/lib/server/forge/core/agentClient.d.ts.map +1 -1
- package/lib/server/forge/core/agentClient.js +10 -25
- package/lib/server/forge/core/agentClient.js.map +1 -1
- package/lib/server/forge/core/claudeClient.d.ts +24 -1
- package/lib/server/forge/core/claudeClient.d.ts.map +1 -1
- package/lib/server/forge/core/claudeClient.js +25 -7
- package/lib/server/forge/core/claudeClient.js.map +1 -1
- package/lib/server/forge/core/configStore.d.ts +11 -1
- package/lib/server/forge/core/configStore.d.ts.map +1 -1
- package/lib/server/forge/core/configStore.js +33 -2
- package/lib/server/forge/core/configStore.js.map +1 -1
- package/lib/server/forge/core/dependencyPaths.d.ts +19 -0
- package/lib/server/forge/core/dependencyPaths.d.ts.map +1 -0
- package/lib/server/forge/core/dependencyPaths.js +32 -0
- package/lib/server/forge/core/dependencyPaths.js.map +1 -0
- package/lib/server/forge/core/evidence.d.ts +43 -0
- package/lib/server/forge/core/evidence.d.ts.map +1 -0
- package/lib/server/forge/core/evidence.js +108 -0
- package/lib/server/forge/core/evidence.js.map +1 -0
- package/lib/server/forge/core/jobs.d.ts +2 -0
- package/lib/server/forge/core/jobs.d.ts.map +1 -1
- package/lib/server/forge/core/jobs.js +8 -0
- package/lib/server/forge/core/jobs.js.map +1 -1
- package/lib/server/forge/core/localRepo.d.ts +31 -10
- package/lib/server/forge/core/localRepo.d.ts.map +1 -1
- package/lib/server/forge/core/localRepo.js +48 -82
- package/lib/server/forge/core/localRepo.js.map +1 -1
- package/lib/server/forge/core/prompts.d.ts +3 -1
- package/lib/server/forge/core/prompts.d.ts.map +1 -1
- package/lib/server/forge/core/prompts.js +14 -5
- package/lib/server/forge/core/prompts.js.map +1 -1
- package/lib/server/forge/core/providers/azuredevops.d.ts +4 -2
- package/lib/server/forge/core/providers/azuredevops.d.ts.map +1 -1
- package/lib/server/forge/core/providers/azuredevops.js +12 -2
- package/lib/server/forge/core/providers/azuredevops.js.map +1 -1
- package/lib/server/forge/core/providers/base.d.ts +29 -4
- package/lib/server/forge/core/providers/base.d.ts.map +1 -1
- package/lib/server/forge/core/providers/base.js +21 -3
- package/lib/server/forge/core/providers/base.js.map +1 -1
- package/lib/server/forge/core/providers/github.d.ts +7 -7
- package/lib/server/forge/core/providers/github.d.ts.map +1 -1
- package/lib/server/forge/core/providers/github.js +13 -4
- package/lib/server/forge/core/providers/github.js.map +1 -1
- package/lib/server/forge/core/providers/gitlab.d.ts +20 -3
- package/lib/server/forge/core/providers/gitlab.d.ts.map +1 -1
- package/lib/server/forge/core/providers/gitlab.js +65 -5
- package/lib/server/forge/core/providers/gitlab.js.map +1 -1
- package/lib/server/forge/core/providers/types.d.ts +20 -0
- package/lib/server/forge/core/providers/types.d.ts.map +1 -1
- package/lib/server/forge/core/secretBox.d.ts +17 -0
- package/lib/server/forge/core/secretBox.d.ts.map +1 -0
- package/lib/server/forge/core/secretBox.js +74 -0
- package/lib/server/forge/core/secretBox.js.map +1 -0
- package/lib/server/forge/core/types.d.ts +7 -1
- package/lib/server/forge/core/types.d.ts.map +1 -1
- package/lib/server/forge/core/validator/clone.d.ts +5 -4
- package/lib/server/forge/core/validator/clone.d.ts.map +1 -1
- package/lib/server/forge/core/validator/clone.js +6 -86
- package/lib/server/forge/core/validator/clone.js.map +1 -1
- package/lib/server/forge/core/validator/cmd.d.ts.map +1 -1
- package/lib/server/forge/core/validator/cmd.js +4 -1
- package/lib/server/forge/core/validator/cmd.js.map +1 -1
- package/lib/server/forge/core/validator/projectType.d.ts.map +1 -1
- package/lib/server/forge/core/validator/projectType.js +2 -1
- package/lib/server/forge/core/validator/projectType.js.map +1 -1
- package/lib/server/forge/core/validator/runners/node.d.ts.map +1 -1
- package/lib/server/forge/core/validator/runners/node.js +6 -2
- package/lib/server/forge/core/validator/runners/node.js.map +1 -1
- package/lib/server/forge/core/validator.d.ts.map +1 -1
- package/lib/server/forge/core/validator.js +28 -22
- package/lib/server/forge/core/validator.js.map +1 -1
- package/lib/server/forge/core/workspaces.d.ts +70 -0
- package/lib/server/forge/core/workspaces.d.ts.map +1 -0
- package/lib/server/forge/core/workspaces.js +348 -0
- package/lib/server/forge/core/workspaces.js.map +1 -0
- package/lib/server/forge/db/database.d.ts +22 -0
- package/lib/server/forge/db/database.d.ts.map +1 -0
- package/lib/server/forge/db/database.js +71 -0
- package/lib/server/forge/db/database.js.map +1 -0
- package/lib/server/forge/db/migrations.d.ts +11 -0
- package/lib/server/forge/db/migrations.d.ts.map +1 -0
- package/lib/server/forge/db/migrations.js +87 -0
- package/lib/server/forge/db/migrations.js.map +1 -0
- package/lib/server/forge/routes.d.ts.map +1 -1
- package/lib/server/forge/routes.js +413 -163
- package/lib/server/forge/routes.js.map +1 -1
- package/lib/server/forge/sse.d.ts +10 -0
- package/lib/server/forge/sse.d.ts.map +1 -0
- package/lib/server/forge/sse.js +22 -0
- package/lib/server/forge/sse.js.map +1 -0
- package/lib/server/spa.d.ts +12 -0
- package/lib/server/spa.d.ts.map +1 -0
- package/lib/server/spa.js +23 -0
- package/lib/server/spa.js.map +1 -0
- package/lib/server.js +9 -24
- package/lib/server.js.map +1 -1
- package/lib/shared/events.d.ts +3 -0
- package/lib/shared/events.d.ts.map +1 -1
- package/lib/shared/events.js +3 -0
- package/lib/shared/events.js.map +1 -1
- package/lib/shared/packageRoot.d.ts +11 -0
- package/lib/shared/packageRoot.d.ts.map +1 -0
- package/lib/shared/packageRoot.js +23 -0
- package/lib/shared/packageRoot.js.map +1 -0
- package/lib/shared/project.d.ts +3 -0
- package/lib/shared/project.d.ts.map +1 -0
- package/lib/shared/project.js +3 -0
- package/lib/shared/project.js.map +1 -0
- package/package.json +24 -9
- package/lib/bin/cli/improve.d.ts +0 -2
- package/lib/bin/cli/improve.d.ts.map +0 -1
- package/lib/bin/cli/improve.js +0 -189
- package/lib/bin/cli/improve.js.map +0 -1
- package/lib/bin/cli/stats.d.ts +0 -2
- package/lib/bin/cli/stats.d.ts.map +0 -1
- package/lib/bin/cli/stats.js +0 -78
- package/lib/bin/cli/stats.js.map +0 -1
- package/lib/server/forge/core/k8s.d.ts +0 -18
- package/lib/server/forge/core/k8s.d.ts.map +0 -1
- package/lib/server/forge/core/k8s.js +0 -49
- package/lib/server/forge/core/k8s.js.map +0 -1
- package/lib/server/forge/core/openclawClient.d.ts +0 -61
- package/lib/server/forge/core/openclawClient.d.ts.map +0 -1
- package/lib/server/forge/core/openclawClient.js +0 -111
- package/lib/server/forge/core/openclawClient.js.map +0 -1
- package/lib/server/forge/core/quotaClient.d.ts +0 -48
- package/lib/server/forge/core/quotaClient.d.ts.map +0 -1
- package/lib/server/forge/core/quotaClient.js +0 -88
- package/lib/server/forge/core/quotaClient.js.map +0 -1
- package/lib/server/forge/core/selfImprove.d.ts +0 -43
- package/lib/server/forge/core/selfImprove.d.ts.map +0 -1
- package/lib/server/forge/core/selfImprove.js +0 -372
- package/lib/server/forge/core/selfImprove.js.map +0 -1
- package/lib/server/forge/core/telemetry.d.ts +0 -100
- package/lib/server/forge/core/telemetry.d.ts.map +0 -1
- package/lib/server/forge/core/telemetry.js +0 -273
- package/lib/server/forge/core/telemetry.js.map +0 -1
- package/scripts/fix-shebang.cjs +0 -11
- package/scripts/inject-readme.cjs +0 -23
- package/scripts/local-rollout.sh +0 -134
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saved analyses, per (repo, issue). The browser used to be the only place a
|
|
3
|
+
* finished analysis lived, so switching tickets mid-run, a second device or a
|
|
4
|
+
* cleared cache lost it. The analyze job now saves its result here before it
|
|
5
|
+
* reports `done`; browsers keep a localStorage copy as a cache.
|
|
6
|
+
*
|
|
7
|
+
* Entries are stored as JSON in the client's StoredAnalysis shape; the server
|
|
8
|
+
* only owns `id`, `ordinal`, `repo` and `analyzedAt`.
|
|
9
|
+
*/
|
|
10
|
+
import type { Db } from "../db/database.ts";
|
|
11
|
+
export declare const MAX_ANALYSES_PER_ISSUE = 5;
|
|
12
|
+
export interface SavedAnalysis {
|
|
13
|
+
id: string;
|
|
14
|
+
ordinal: number;
|
|
15
|
+
result: {
|
|
16
|
+
explanation: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
};
|
|
19
|
+
analyzedAt: string;
|
|
20
|
+
repo: string;
|
|
21
|
+
model: string;
|
|
22
|
+
mrIid?: number;
|
|
23
|
+
prompt?: string;
|
|
24
|
+
refineThread?: unknown[];
|
|
25
|
+
claudeSessionId?: string;
|
|
26
|
+
validation?: unknown;
|
|
27
|
+
}
|
|
28
|
+
export declare function createAnalysisStore({ db, clock }: {
|
|
29
|
+
db: Db;
|
|
30
|
+
clock?: () => number;
|
|
31
|
+
}): {
|
|
32
|
+
list: (repo: string, issueIid: number) => Promise<SavedAnalysis[]>;
|
|
33
|
+
/** Saves a finished analyze job. Calling it again for the same job returns the saved entry. */
|
|
34
|
+
create: ({ repo, issueIid, id, result, model, mrIid, prompt }: {
|
|
35
|
+
repo: string;
|
|
36
|
+
issueIid: number;
|
|
37
|
+
id: string;
|
|
38
|
+
result: SavedAnalysis["result"];
|
|
39
|
+
model: string;
|
|
40
|
+
mrIid?: number;
|
|
41
|
+
prompt?: string;
|
|
42
|
+
}) => Promise<SavedAnalysis>;
|
|
43
|
+
/**
|
|
44
|
+
* Saves a browser's copy of an analysis: refine turns and validation on a
|
|
45
|
+
* known entry, or an entry only that browser had. A new entry whose
|
|
46
|
+
* ordinal is taken gets the next free one; the caller adopts the result.
|
|
47
|
+
*/
|
|
48
|
+
put: (repo: string, issueIid: number, entry: SavedAnalysis) => Promise<SavedAnalysis>;
|
|
49
|
+
remove: (repo: string, issueIid: number, id: string) => Promise<void>;
|
|
50
|
+
clear: (repo: string, issueIid: number) => Promise<void>;
|
|
51
|
+
};
|
|
52
|
+
export type AnalysisStore = ReturnType<typeof createAnalysisStore>;
|
|
53
|
+
//# sourceMappingURL=analysisStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysisStore.d.ts","sourceRoot":"","sources":["../../../../server/forge/analyses/analysisStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAE5C,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAMD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,EAAE,KAAgB,EAAE,EAAE;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE;iBACnE,MAAM,YAAY,MAAM,KAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAsC5E,+FAA+F;mEAChC;QAC9D,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KAChB;IAmBD;;;;OAIG;gBACS,MAAM,YAAY,MAAM,SAAS,aAAa;mBAarC,MAAM,YAAY,MAAM,MAAM,MAAM;kBAIrC,MAAM,YAAY,MAAM;EAI7C;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saved analyses, per (repo, issue). The browser used to be the only place a
|
|
3
|
+
* finished analysis lived, so switching tickets mid-run, a second device or a
|
|
4
|
+
* cleared cache lost it. The analyze job now saves its result here before it
|
|
5
|
+
* reports `done`; browsers keep a localStorage copy as a cache.
|
|
6
|
+
*
|
|
7
|
+
* Entries are stored as JSON in the client's StoredAnalysis shape; the server
|
|
8
|
+
* only owns `id`, `ordinal`, `repo` and `analyzedAt`.
|
|
9
|
+
*/
|
|
10
|
+
export const MAX_ANALYSES_PER_ISSUE = 5;
|
|
11
|
+
export function createAnalysisStore({ db, clock = Date.now }) {
|
|
12
|
+
const list = async (repo, issueIid) => {
|
|
13
|
+
const rows = await db.all("SELECT data FROM analyses WHERE repo = ? AND issue_iid = ? ORDER BY ordinal DESC", [repo, issueIid]);
|
|
14
|
+
return rows.map((r) => JSON.parse(r.data));
|
|
15
|
+
};
|
|
16
|
+
const nextOrdinal = async (repo, issueIid) => {
|
|
17
|
+
const row = await db.get("SELECT MAX(ordinal) AS max FROM analyses WHERE repo = ? AND issue_iid = ?", [repo, issueIid]);
|
|
18
|
+
return (row?.max ?? 0) + 1;
|
|
19
|
+
};
|
|
20
|
+
const write = async (repo, issueIid, entry) => {
|
|
21
|
+
await db.run(`INSERT INTO analyses (repo, issue_iid, id, ordinal, data, updated_at) VALUES (?, ?, ?, ?, ?, ?)
|
|
22
|
+
ON CONFLICT (repo, issue_iid, id) DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`, [repo, issueIid, entry.id, entry.ordinal, JSON.stringify(entry), clock()]);
|
|
23
|
+
// Keep the newest MAX_ANALYSES_PER_ISSUE, same as the browser cache did.
|
|
24
|
+
await db.run(`DELETE FROM analyses WHERE repo = ? AND issue_iid = ? AND ordinal NOT IN
|
|
25
|
+
(SELECT ordinal FROM analyses WHERE repo = ? AND issue_iid = ? ORDER BY ordinal DESC LIMIT ?)`, [repo, issueIid, repo, issueIid, MAX_ANALYSES_PER_ISSUE]);
|
|
26
|
+
};
|
|
27
|
+
const find = async (repo, issueIid, id) => {
|
|
28
|
+
const row = await db.get("SELECT data FROM analyses WHERE repo = ? AND issue_iid = ? AND id = ?", [repo, issueIid, id]);
|
|
29
|
+
return row ? JSON.parse(row.data) : null;
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
list,
|
|
33
|
+
/** Saves a finished analyze job. Calling it again for the same job returns the saved entry. */
|
|
34
|
+
create: ({ repo, issueIid, id, result, model, mrIid, prompt }) => db.transaction(async () => {
|
|
35
|
+
const existing = await find(repo, issueIid, id);
|
|
36
|
+
if (existing)
|
|
37
|
+
return existing;
|
|
38
|
+
const trimmed = prompt?.trim();
|
|
39
|
+
const entry = {
|
|
40
|
+
id,
|
|
41
|
+
ordinal: await nextOrdinal(repo, issueIid),
|
|
42
|
+
result,
|
|
43
|
+
analyzedAt: new Date(clock()).toISOString(),
|
|
44
|
+
repo,
|
|
45
|
+
model,
|
|
46
|
+
...(mrIid !== undefined && { mrIid }),
|
|
47
|
+
...(trimmed && { prompt: trimmed }),
|
|
48
|
+
};
|
|
49
|
+
await write(repo, issueIid, entry);
|
|
50
|
+
return entry;
|
|
51
|
+
}),
|
|
52
|
+
/**
|
|
53
|
+
* Saves a browser's copy of an analysis: refine turns and validation on a
|
|
54
|
+
* known entry, or an entry only that browser had. A new entry whose
|
|
55
|
+
* ordinal is taken gets the next free one; the caller adopts the result.
|
|
56
|
+
*/
|
|
57
|
+
put: (repo, issueIid, entry) => db.transaction(async () => {
|
|
58
|
+
const existing = await find(repo, issueIid, entry.id);
|
|
59
|
+
let ordinal = existing?.ordinal ?? entry.ordinal;
|
|
60
|
+
if (!existing) {
|
|
61
|
+
const taken = await db.get("SELECT 1 FROM analyses WHERE repo = ? AND issue_iid = ? AND ordinal = ?", [repo, issueIid, ordinal]);
|
|
62
|
+
if (taken || !Number.isInteger(ordinal) || ordinal < 1)
|
|
63
|
+
ordinal = await nextOrdinal(repo, issueIid);
|
|
64
|
+
}
|
|
65
|
+
const saved = { ...entry, ordinal, repo };
|
|
66
|
+
await write(repo, issueIid, saved);
|
|
67
|
+
return saved;
|
|
68
|
+
}),
|
|
69
|
+
remove: async (repo, issueIid, id) => {
|
|
70
|
+
await db.run("DELETE FROM analyses WHERE repo = ? AND issue_iid = ? AND id = ?", [repo, issueIid, id]);
|
|
71
|
+
},
|
|
72
|
+
clear: async (repo, issueIid) => {
|
|
73
|
+
await db.run("DELETE FROM analyses WHERE repo = ? AND issue_iid = ?", [repo, issueIid]);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=analysisStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysisStore.js","sourceRoot":"","sources":["../../../../server/forge/analyses/analysisStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Db } from "../db/database.ts";
|
|
2
|
+
export declare const API_TOKEN_PREFIX = "forge_pat_";
|
|
3
|
+
export interface ApiTokenRecord {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
prefix: string;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
lastUsedAt: number | null;
|
|
9
|
+
}
|
|
10
|
+
/** Personal access tokens for the CLI and automation. Shown once, stored hashed. */
|
|
11
|
+
export declare function createApiTokens({ db, clock }: {
|
|
12
|
+
db: Db;
|
|
13
|
+
clock?: () => number;
|
|
14
|
+
}): {
|
|
15
|
+
create({ userId, name }: {
|
|
16
|
+
userId: string;
|
|
17
|
+
name: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
token: string;
|
|
20
|
+
record: ApiTokenRecord;
|
|
21
|
+
}>;
|
|
22
|
+
list(userId: string): Promise<ApiTokenRecord[]>;
|
|
23
|
+
resolve(token: string): Promise<{
|
|
24
|
+
userId: string;
|
|
25
|
+
tokenId: string;
|
|
26
|
+
}>;
|
|
27
|
+
revoke({ id, userId }: {
|
|
28
|
+
id: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
}): Promise<boolean>;
|
|
31
|
+
revokeAllForUser(userId: string): Promise<void>;
|
|
32
|
+
};
|
|
33
|
+
export type ApiTokens = ReturnType<typeof createApiTokens>;
|
|
34
|
+
//# sourceMappingURL=apiTokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiTokens.d.ts","sourceRoot":"","sources":["../../../../server/forge/auth/apiTokens.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAI5C,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAoBD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,EAAE,EAAE,EAAE,KAAgB,EAAE,EAAE;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE;6BAEzD;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;;;;iBAW5C,MAAM;mBAMJ,MAAM;;;;2BAOE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;6BAS5B,MAAM;EAItC;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { newSecret, sha256 } from "./tokenHash.js";
|
|
3
|
+
export const API_TOKEN_PREFIX = "forge_pat_";
|
|
4
|
+
const toRecord = (r) => ({
|
|
5
|
+
id: r.id,
|
|
6
|
+
name: r.name,
|
|
7
|
+
prefix: r.prefix,
|
|
8
|
+
createdAt: r.created_at,
|
|
9
|
+
lastUsedAt: r.last_used_at,
|
|
10
|
+
});
|
|
11
|
+
/** Personal access tokens for the CLI and automation. Shown once, stored hashed. */
|
|
12
|
+
export function createApiTokens({ db, clock = Date.now }) {
|
|
13
|
+
return {
|
|
14
|
+
async create({ userId, name }) {
|
|
15
|
+
const token = `${API_TOKEN_PREFIX}${newSecret()}`;
|
|
16
|
+
const id = randomUUID();
|
|
17
|
+
await db.run("INSERT INTO api_tokens (id, user_id, name, token_hash, prefix, created_at) VALUES (?, ?, ?, ?, ?, ?)", [id, userId, name.trim().slice(0, 80) || "API token", sha256(token), token.slice(0, API_TOKEN_PREFIX.length + 8), clock()]);
|
|
18
|
+
const row = (await db.get("SELECT * FROM api_tokens WHERE id = ?", [id]));
|
|
19
|
+
return { token, record: toRecord(row) };
|
|
20
|
+
},
|
|
21
|
+
async list(userId) {
|
|
22
|
+
return (await db.all("SELECT * FROM api_tokens WHERE user_id = ? AND revoked_at IS NULL ORDER BY created_at DESC", [userId])).map(toRecord);
|
|
23
|
+
},
|
|
24
|
+
async resolve(token) {
|
|
25
|
+
const row = await db.get("SELECT * FROM api_tokens WHERE token_hash = ? AND revoked_at IS NULL", [sha256(token)]);
|
|
26
|
+
if (!row)
|
|
27
|
+
return null;
|
|
28
|
+
await db.run("UPDATE api_tokens SET last_used_at = ? WHERE id = ?", [clock(), row.id]);
|
|
29
|
+
return { userId: row.user_id, tokenId: row.id };
|
|
30
|
+
},
|
|
31
|
+
async revoke({ id, userId }) {
|
|
32
|
+
const r = await db.run("UPDATE api_tokens SET revoked_at = ? WHERE id = ? AND user_id = ? AND revoked_at IS NULL", [
|
|
33
|
+
clock(),
|
|
34
|
+
id,
|
|
35
|
+
userId,
|
|
36
|
+
]);
|
|
37
|
+
return r.changes > 0;
|
|
38
|
+
},
|
|
39
|
+
async revokeAllForUser(userId) {
|
|
40
|
+
await db.run("UPDATE api_tokens SET revoked_at = ? WHERE user_id = ? AND revoked_at IS NULL", [clock(), userId]);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=apiTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiTokens.js","sourceRoot":"","sources":["../../../../server/forge/auth/apiTokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAoB7C,MAAM,QAAQ,GAAG,CAAC,CAAM,EAAkB,EAAE,CAAC,CAAC;IAC7C,EAAE,EAAE,CAAC,CAAC,EAAE;IACR,IAAI,EAAE,CAAC,CAAC,IAAI;IACZ,MAAM,EAAE,CAAC,CAAC,MAAM;IAChB,SAAS,EAAE,CAAC,CAAC,UAAU;IACvB,UAAU,EAAE,CAAC,CAAC,YAAY;CAC1B,CAAC,CAAC;AAEH,oFAAoF;AACpF,MAAM,UAAU,eAAe,CAAC,EAAE,EAAE,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,EAAoC;IACzF,OAAO;QACN,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAoC;YAC9D,MAAM,KAAK,GAAG,GAAG,gBAAgB,GAAG,SAAS,EAAE,EAAE,CAAC;YAClD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;YACxB,MAAM,EAAE,CAAC,GAAG,CACX,sGAAsG,EACtG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAC1H,CAAC;YACF,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAM,uCAAuC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAE,CAAC;YAChF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAc;YACxB,OAAO,CACN,MAAM,EAAE,CAAC,GAAG,CAAM,4FAA4F,EAAE,CAAC,MAAM,CAAC,CAAC,CACzH,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjB,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,KAAa;YAC1B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CAAM,sEAAsE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvH,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtB,MAAM,EAAE,CAAC,GAAG,CAAC,qDAAqD,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACvF,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACjD,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAkC;YAC1D,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,0FAA0F,EAAE;gBAClH,KAAK,EAAE;gBACP,EAAE;gBACF,MAAM;aACN,CAAC,CAAC;YACH,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,MAAc;YACpC,MAAM,EAAE,CAAC,GAAG,CAAC,+EAA+E,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QAClH,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Db } from "../db/database.ts";
|
|
2
|
+
export type AuditOutcome = "success" | "failure" | "denied";
|
|
3
|
+
export interface AuditEventInput {
|
|
4
|
+
actorId: string | null;
|
|
5
|
+
actorLabel: string;
|
|
6
|
+
action: string;
|
|
7
|
+
outcome: AuditOutcome;
|
|
8
|
+
target?: string | null;
|
|
9
|
+
repo?: string | null;
|
|
10
|
+
ip?: string | null;
|
|
11
|
+
userAgent?: string | null;
|
|
12
|
+
details?: Record<string, unknown> | null;
|
|
13
|
+
}
|
|
14
|
+
export interface AuditEvent extends Required<Omit<AuditEventInput, "details">> {
|
|
15
|
+
id: number;
|
|
16
|
+
at: number;
|
|
17
|
+
details: Record<string, unknown> | null;
|
|
18
|
+
}
|
|
19
|
+
/** Append-only. There is deliberately no update or delete. */
|
|
20
|
+
export declare function createAuditLog({ db, clock }: {
|
|
21
|
+
db: Db;
|
|
22
|
+
clock?: () => number;
|
|
23
|
+
}): {
|
|
24
|
+
record(e: AuditEventInput): Promise<void>;
|
|
25
|
+
list({ action, actorId, limit, before }: {
|
|
26
|
+
action?: string;
|
|
27
|
+
actorId?: string;
|
|
28
|
+
limit?: number;
|
|
29
|
+
before?: number;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
events: AuditEvent[];
|
|
32
|
+
nextCursor: number;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
export type AuditLog = ReturnType<typeof createAuditLog>;
|
|
36
|
+
//# sourceMappingURL=auditLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditLog.d.ts","sourceRoot":"","sources":["../../../../server/forge/auth/auditLog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAE5C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAC7E,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACxC;AAkBD,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,KAAgB,EAAE,EAAE;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;CAAE;cAEvE,eAAe;6CAkBqB;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;;EAyC3H;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const MAX_PAGE = 200;
|
|
2
|
+
/** Append-only. There is deliberately no update or delete. */
|
|
3
|
+
export function createAuditLog({ db, clock = Date.now }) {
|
|
4
|
+
return {
|
|
5
|
+
async record(e) {
|
|
6
|
+
await db.run("INSERT INTO audit_events (at, actor_id, actor_label, action, target, repo, outcome, ip, user_agent, details) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
|
|
7
|
+
clock(),
|
|
8
|
+
e.actorId,
|
|
9
|
+
e.actorLabel,
|
|
10
|
+
e.action,
|
|
11
|
+
e.target ?? null,
|
|
12
|
+
e.repo ?? null,
|
|
13
|
+
e.outcome,
|
|
14
|
+
e.ip ?? null,
|
|
15
|
+
e.userAgent?.slice(0, 300) ?? null,
|
|
16
|
+
e.details ? JSON.stringify(e.details) : null,
|
|
17
|
+
]);
|
|
18
|
+
},
|
|
19
|
+
async list({ action, actorId, limit = 50, before }) {
|
|
20
|
+
const where = [];
|
|
21
|
+
const params = [];
|
|
22
|
+
if (action) {
|
|
23
|
+
where.push("action = ?");
|
|
24
|
+
params.push(action);
|
|
25
|
+
}
|
|
26
|
+
if (actorId) {
|
|
27
|
+
where.push("actor_id = ?");
|
|
28
|
+
params.push(actorId);
|
|
29
|
+
}
|
|
30
|
+
if (before) {
|
|
31
|
+
where.push("id < ?");
|
|
32
|
+
params.push(before);
|
|
33
|
+
}
|
|
34
|
+
const size = Math.min(Math.max(1, limit), MAX_PAGE);
|
|
35
|
+
const rows = await db.all(`SELECT * FROM audit_events ${where.length ? `WHERE ${where.join(" AND ")}` : ""} ORDER BY id DESC LIMIT ?`, [...params, size + 1]);
|
|
36
|
+
const page = rows.slice(0, size);
|
|
37
|
+
return {
|
|
38
|
+
events: page.map((r) => ({
|
|
39
|
+
id: r.id,
|
|
40
|
+
at: r.at,
|
|
41
|
+
actorId: r.actor_id,
|
|
42
|
+
actorLabel: r.actor_label,
|
|
43
|
+
action: r.action,
|
|
44
|
+
target: r.target,
|
|
45
|
+
repo: r.repo,
|
|
46
|
+
outcome: r.outcome,
|
|
47
|
+
ip: r.ip,
|
|
48
|
+
userAgent: r.user_agent,
|
|
49
|
+
details: r.details ? JSON.parse(r.details) : null,
|
|
50
|
+
})),
|
|
51
|
+
nextCursor: rows.length > size ? page[page.length - 1].id : null,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=auditLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditLog.js","sourceRoot":"","sources":["../../../../server/forge/auth/auditLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OidcOptions } from "./oidc.ts";
|
|
2
|
+
type Env = Record<string, string | undefined>;
|
|
3
|
+
export interface AuthConfig {
|
|
4
|
+
serviceToken?: string;
|
|
5
|
+
cookieSecure: boolean;
|
|
6
|
+
oidc?: OidcOptions;
|
|
7
|
+
}
|
|
8
|
+
/** Reads auth settings from the environment; throws on half-configured SSO. */
|
|
9
|
+
export declare function authConfigFromEnv(env: Env, { isProd }: {
|
|
10
|
+
isProd: boolean;
|
|
11
|
+
}): AuthConfig;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=authConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authConfig.d.ts","sourceRoot":"","sources":["../../../../server/forge/auth/authConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,WAAW,UAAU;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;CACnB;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,UAAU,CAiCvF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isRole } from "./roles.js";
|
|
2
|
+
/** Reads auth settings from the environment; throws on half-configured SSO. */
|
|
3
|
+
export function authConfigFromEnv(env, { isProd }) {
|
|
4
|
+
const serviceToken = env.FORGE_DISABLE_SERVICE_TOKEN === "1" ? undefined : env.FORGE_TOKEN || undefined;
|
|
5
|
+
const cookieSecure = env.FORGE_COOKIE_SECURE ? env.FORGE_COOKIE_SECURE === "1" : isProd;
|
|
6
|
+
if (!env.FORGE_OIDC_ISSUER)
|
|
7
|
+
return { serviceToken, cookieSecure };
|
|
8
|
+
for (const key of ["FORGE_OIDC_CLIENT_ID", "FORGE_OIDC_CLIENT_SECRET"]) {
|
|
9
|
+
if (!env[key])
|
|
10
|
+
throw new Error(`${key} is required when FORGE_OIDC_ISSUER is set.`);
|
|
11
|
+
}
|
|
12
|
+
const redirectUri = env.FORGE_OIDC_REDIRECT_URI ??
|
|
13
|
+
(env.FORGE_PUBLIC_URL ? `${env.FORGE_PUBLIC_URL.replace(/\/$/, "")}/api/forge/auth/oidc/callback` : undefined);
|
|
14
|
+
if (!redirectUri)
|
|
15
|
+
throw new Error("Set FORGE_PUBLIC_URL (or FORGE_OIDC_REDIRECT_URI) to enable single sign-on.");
|
|
16
|
+
const defaultRole = env.FORGE_OIDC_DEFAULT_ROLE ?? "viewer";
|
|
17
|
+
if (!isRole(defaultRole))
|
|
18
|
+
throw new Error(`FORGE_OIDC_DEFAULT_ROLE must be viewer, operator, approver or admin.`);
|
|
19
|
+
return {
|
|
20
|
+
serviceToken,
|
|
21
|
+
cookieSecure,
|
|
22
|
+
oidc: {
|
|
23
|
+
issuer: env.FORGE_OIDC_ISSUER,
|
|
24
|
+
clientId: env.FORGE_OIDC_CLIENT_ID,
|
|
25
|
+
clientSecret: env.FORGE_OIDC_CLIENT_SECRET,
|
|
26
|
+
redirectUri,
|
|
27
|
+
allowedDomains: (env.FORGE_OIDC_ALLOWED_DOMAINS ?? "")
|
|
28
|
+
.split(",")
|
|
29
|
+
.map((d) => d.trim().toLowerCase())
|
|
30
|
+
.filter(Boolean),
|
|
31
|
+
defaultRole,
|
|
32
|
+
name: env.FORGE_OIDC_NAME || "SSO",
|
|
33
|
+
scopes: env.FORGE_OIDC_SCOPES,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=authConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authConfig.js","sourceRoot":"","sources":["../../../../server/forge/auth/authConfig.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAUpC,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,GAAQ,EAAE,EAAE,MAAM,EAAuB;IAC1E,MAAM,YAAY,GAAG,GAAG,CAAC,2BAA2B,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,CAAC;IACxG,MAAM,YAAY,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAExF,IAAI,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IAElE,KAAK,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,0BAA0B,CAAC,EAAE,CAAC;QACxE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,6CAA6C,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,WAAW,GAChB,GAAG,CAAC,uBAAuB;QAC3B,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,+BAA+B,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAChH,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjH,MAAM,WAAW,GAAG,GAAG,CAAC,uBAAuB,IAAI,QAAQ,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAElH,OAAO;QACN,YAAY;QACZ,YAAY;QACZ,IAAI,EAAE;YACL,MAAM,EAAE,GAAG,CAAC,iBAAiB;YAC7B,QAAQ,EAAE,GAAG,CAAC,oBAAqB;YACnC,YAAY,EAAE,GAAG,CAAC,wBAAyB;YAC3C,WAAW;YACX,cAAc,EAAE,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC;iBACpD,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;iBAClC,MAAM,CAAC,OAAO,CAAC;YACjB,WAAW;YACX,IAAI,EAAE,GAAG,CAAC,eAAe,IAAI,KAAK;YAClC,MAAM,EAAE,GAAG,CAAC,iBAAiB;SAC7B;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { type NextFunction, type Request, type Response } from "express";
|
|
2
|
+
import type { Db } from "../db/database.ts";
|
|
3
|
+
import { type OidcOptions } from "./oidc.ts";
|
|
4
|
+
import { requireRole } from "./middleware.ts";
|
|
5
|
+
import { type Role } from "./roles.ts";
|
|
6
|
+
import { type User } from "./users.ts";
|
|
7
|
+
export interface Principal {
|
|
8
|
+
id: string;
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
role: Role;
|
|
12
|
+
kind: "user" | "token" | "service";
|
|
13
|
+
}
|
|
14
|
+
declare global {
|
|
15
|
+
namespace Express {
|
|
16
|
+
interface Request {
|
|
17
|
+
principal?: Principal;
|
|
18
|
+
authVia?: "cookie" | "bearer";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export interface AuthOptions {
|
|
23
|
+
db: Db;
|
|
24
|
+
/** FORGE_TOKEN: admin service credential for the CLI and the first-run setup secret. */
|
|
25
|
+
serviceToken?: string;
|
|
26
|
+
/** Called once at startup with the code remote visitors need to create the first admin. */
|
|
27
|
+
onSetupCode?: (code: string) => void;
|
|
28
|
+
cookieSecure: boolean;
|
|
29
|
+
oidc?: OidcOptions;
|
|
30
|
+
clock?: () => number;
|
|
31
|
+
sessionIdleMs?: number;
|
|
32
|
+
sessionAbsoluteMs?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare const CSRF_HEADER = "x-forge-request";
|
|
35
|
+
/**
|
|
36
|
+
* True only for a browser on the server machine talking to Forge directly:
|
|
37
|
+
* loopback socket, no proxy headers (a reverse proxy on the same host would
|
|
38
|
+
* otherwise make every visitor look local), and a localhost Host header (so a
|
|
39
|
+
* DNS-rebinding page can't pose as local).
|
|
40
|
+
*/
|
|
41
|
+
export declare function isLocalRequest(req: Request): boolean;
|
|
42
|
+
/** Only same-origin relative paths; anything else (incl. `//host`) → "/". */
|
|
43
|
+
export declare function safeReturnTo(value: unknown): string;
|
|
44
|
+
export declare function createAuth(opts: AuthOptions): {
|
|
45
|
+
users: {
|
|
46
|
+
count(): Promise<number>;
|
|
47
|
+
countActiveAdmins(): Promise<number>;
|
|
48
|
+
findById(id: string): Promise<User>;
|
|
49
|
+
findByEmail(email: string): Promise<User>;
|
|
50
|
+
list(): Promise<User[]>;
|
|
51
|
+
create({ email, name, role, password }: {
|
|
52
|
+
email: string;
|
|
53
|
+
name: string;
|
|
54
|
+
role: Role;
|
|
55
|
+
password?: string;
|
|
56
|
+
}): Promise<User>;
|
|
57
|
+
update(id: string, patch: {
|
|
58
|
+
role?: Role;
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
name?: string;
|
|
61
|
+
password?: string;
|
|
62
|
+
}): Promise<User>;
|
|
63
|
+
authenticate(email: string, password: string): Promise<import("./users.ts").AuthResult>;
|
|
64
|
+
upsertOidc({ subject, email, name, defaultRole }: {
|
|
65
|
+
subject: string;
|
|
66
|
+
email: string;
|
|
67
|
+
name: string;
|
|
68
|
+
defaultRole: Role;
|
|
69
|
+
}): Promise<User>;
|
|
70
|
+
};
|
|
71
|
+
sessions: {
|
|
72
|
+
absoluteMs: number;
|
|
73
|
+
create({ userId, ip, userAgent }: {
|
|
74
|
+
userId: string;
|
|
75
|
+
ip: string;
|
|
76
|
+
userAgent: string;
|
|
77
|
+
}): Promise<{
|
|
78
|
+
token: string;
|
|
79
|
+
}>;
|
|
80
|
+
resolve(token: string): Promise<{
|
|
81
|
+
userId: string;
|
|
82
|
+
createdAt: number;
|
|
83
|
+
}>;
|
|
84
|
+
revoke(token: string): Promise<void>;
|
|
85
|
+
revokeAllForUser(userId: string): Promise<void>;
|
|
86
|
+
};
|
|
87
|
+
tokens: {
|
|
88
|
+
create({ userId, name }: {
|
|
89
|
+
userId: string;
|
|
90
|
+
name: string;
|
|
91
|
+
}): Promise<{
|
|
92
|
+
token: string;
|
|
93
|
+
record: import("./apiTokens.ts").ApiTokenRecord;
|
|
94
|
+
}>;
|
|
95
|
+
list(userId: string): Promise<import("./apiTokens.ts").ApiTokenRecord[]>;
|
|
96
|
+
resolve(token: string): Promise<{
|
|
97
|
+
userId: string;
|
|
98
|
+
tokenId: string;
|
|
99
|
+
}>;
|
|
100
|
+
revoke({ id, userId }: {
|
|
101
|
+
id: string;
|
|
102
|
+
userId: string;
|
|
103
|
+
}): Promise<boolean>;
|
|
104
|
+
revokeAllForUser(userId: string): Promise<void>;
|
|
105
|
+
};
|
|
106
|
+
audit: {
|
|
107
|
+
record(e: import("./auditLog.ts").AuditEventInput): Promise<void>;
|
|
108
|
+
list({ action, actorId, limit, before }: {
|
|
109
|
+
action?: string;
|
|
110
|
+
actorId?: string;
|
|
111
|
+
limit?: number;
|
|
112
|
+
before?: number;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
events: import("./auditLog.ts").AuditEvent[];
|
|
115
|
+
nextCursor: number;
|
|
116
|
+
}>;
|
|
117
|
+
};
|
|
118
|
+
router: import("express-serve-static-core").Router;
|
|
119
|
+
adminRouter: import("express-serve-static-core").Router;
|
|
120
|
+
authenticate: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
121
|
+
requireUser: (req: Request, res: Response, next: NextFunction) => void;
|
|
122
|
+
requireRole: typeof requireRole;
|
|
123
|
+
csrf: (req: Request, res: Response, next: NextFunction) => void;
|
|
124
|
+
auditTrail: (req: Request, res: Response, next: NextFunction) => void;
|
|
125
|
+
/** Logs the setup code while no admin exists (only when it was generated). */
|
|
126
|
+
announceSetup: () => Promise<void>;
|
|
127
|
+
setOidcRedirectUri: (uri: string) => void;
|
|
128
|
+
};
|
|
129
|
+
export type Auth = ReturnType<typeof createAuth>;
|
|
130
|
+
//# sourceMappingURL=createAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAuth.d.ts","sourceRoot":"","sources":["../../../../server/forge/auth/createAuth.ts"],"names":[],"mappings":"AAEA,OAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAElF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAI5C,OAAO,EAAoB,KAAK,WAAW,EAAe,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAU,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACnC;AAED,OAAO,CAAC,MAAM,CAAC;IAEd,UAAU,OAAO,CAAC;QACjB,UAAU,OAAO;YAChB,SAAS,CAAC,EAAE,SAAS,CAAC;YACtB,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;SAC9B;KACD;CACD;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,EAAE,CAAC;IACP,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2FAA2F;IAC3F,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAGD,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAa7C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAKpD;AAiBD,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAInD;AAaD,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW;;;;;;;;;;;oBArCpC,CAAC;;;gBAoBW,CAAC;oBAAgB,CAAC;gBAAe,CAAC;oBACrC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAxCS,CAAC;mBAC1B,CAAC;iBAAe,CAAC;kBACV,CAAA;;;;;;;;wBAqHyB,OAAO,OAAO,QAAQ,QAAQ,YAAY;uBAcjD,OAAO,OAAO,QAAQ,QAAQ,YAAY;;gBASjD,OAAO,OAAO,QAAQ,QAAQ,YAAY;sBASpC,OAAO,OAAO,QAAQ,QAAQ,YAAY;IAwOlE,8EAA8E;;8BAMpD,MAAM;EAIjC;AAED,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
|