@preventive/triage 1.0.0-alpha.4 → 1.0.0-alpha.41
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-APACHE +202 -0
- package/README.md +16 -0
- package/api/reap.ts +17 -0
- package/cli.js +6 -0
- package/client/dependency-paths.d.ts +2 -0
- package/client/dependency-paths.js +24 -0
- package/client/finding-link.js +305 -0
- package/client/linked-findings.d.ts +1 -0
- package/client/linked-findings.js +112 -0
- package/common/bundle-commit.d.ts +1 -0
- package/common/bundle-commit.js +4 -0
- package/common/bundle-compare-diff.d.ts +3 -0
- package/common/bundle-compare-diff.js +522 -0
- package/common/bundle-compare-inputs.d.ts +2 -0
- package/common/bundle-compare-inputs.js +65 -0
- package/common/bundle-metadata.d.ts +14 -0
- package/common/bundle-metadata.js +226 -0
- package/common/bundle-pkg-of.d.ts +1 -0
- package/common/bundle-pkg-of.js +90 -0
- package/common/bundle-reasons.d.ts +2 -0
- package/common/bundle-reasons.js +21 -0
- package/common/bundle-source-links.d.ts +6 -0
- package/common/bundle-source-links.js +216 -0
- package/common/bundle-sourcemap.d.ts +10 -0
- package/common/bundle-sourcemap.js +100 -0
- package/common/bundle-sources.d.ts +7 -0
- package/common/bundle-sources.js +310 -0
- package/common/bundle-stats.js +41 -0
- package/common/bundle-tabs.js +1 -0
- package/common/code-language.js +65 -0
- package/common/default-scan-models.ts +31 -0
- package/common/dependency-reviews.d.ts +23 -0
- package/common/dependency-reviews.js +81 -0
- package/common/finding-duplicates.js +58 -0
- package/common/finding-filters.js +274 -0
- package/common/finding-id.js +47 -0
- package/common/github-issue-labels.d.ts +1 -0
- package/common/github-issue-labels.js +11 -0
- package/common/github-pr.ts +56 -0
- package/common/gzip.js +59 -0
- package/common/line-diff.d.ts +8 -0
- package/common/line-diff.js +56 -0
- package/common/linked-workspace-groups.js +63 -0
- package/common/managed/comments.ts +34 -0
- package/common/managed/npm-packages.d.ts +5 -0
- package/common/managed/npm-packages.js +34 -0
- package/common/managed/permissions.ts +31 -0
- package/common/managed/report-content.ts +72 -0
- package/common/managed/report-filter.ts +108 -0
- package/common/managed/repository-alias.ts +65 -0
- package/common/managed/roles.ts +28 -0
- package/common/managed/routes.d.ts +2 -0
- package/common/managed/routes.js +254 -0
- package/common/managed/scan-models.ts +6 -0
- package/common/managed/team-app.d.ts +2 -0
- package/common/managed/team-app.js +31 -0
- package/common/managed/triage.ts +83 -0
- package/common/managed/upload-seal.ts +126 -0
- package/common/pretty-print.d.ts +5 -0
- package/common/pretty-print.js +24 -0
- package/common/revalidation-conflicts.js +48 -0
- package/common/revalidation-input-groups.js +56 -0
- package/common/save-error-reason.ts +20 -7
- package/common/scan-server.ts +13 -0
- package/common/server-info.ts +35 -0
- package/common/utf8.d.ts +3 -0
- package/common/utf8.js +45 -0
- package/common/workspace-app.js +23 -0
- package/common/workspace-groups.js +176 -0
- package/out/brotli-fallback.js +3 -3
- package/out/chunk-2AFQKRAM.js +51 -0
- package/out/chunk-2KBF5TZ7.js +2 -0
- package/out/chunk-2XUEZHIP.js +28 -0
- package/out/chunk-35VE6CDH.js +2 -0
- package/out/chunk-3BZ7JERB.js +1 -0
- package/out/chunk-4F6JSF57.js +3 -0
- package/out/chunk-4XCDFGDP.js +10 -0
- package/out/chunk-C4Z6ZBXV.js +10 -0
- package/out/chunk-CMQA4DM6.js +1 -0
- package/out/chunk-CVVJAXVY.js +2 -0
- package/out/chunk-DIJJNTRH.js +10 -0
- package/out/chunk-GJ4IUCNS.js +1 -0
- package/out/chunk-GNXOKIGP.js +80 -0
- package/out/chunk-GZ4MS3TE.js +13 -0
- package/out/chunk-IU3CCINR.js +3 -0
- package/out/chunk-K3X5EJBQ.js +2 -0
- package/out/chunk-KEX2ATEW.js +2 -0
- package/out/chunk-KVEUXIEU.js +1 -0
- package/out/chunk-KYCNJVB7.js +1 -0
- package/out/chunk-NRPC74AM.js +1 -0
- package/out/chunk-OOJM4CTU.js +1 -0
- package/out/chunk-PNHBZGDD.js +1 -0
- package/out/chunk-QZ3A376W.js +1 -0
- package/out/chunk-R5O6FAW4.js +2 -0
- package/out/chunk-RFZQQXSG.js +17 -0
- package/out/chunk-RSHMVYNS.js +1 -0
- package/out/chunk-TUII34K2.js +1 -0
- package/out/chunk-TY4RZD3Z.js +226 -0
- package/out/chunk-TZ5KB2Y5.js +10 -0
- package/out/chunk-U6OPEXIA.js +1 -0
- package/out/chunk-UNTRGE26.js +2 -0
- package/out/chunk-UXNUAIIC.js +33 -0
- package/out/chunk-UYAXVRVL.js +1 -0
- package/out/chunk-UZAZM2SX.js +2 -0
- package/out/chunk-V3ME6FI5.js +2 -0
- package/out/chunk-V5O7M2YT.js +1 -0
- package/out/chunk-VIHGO77Y.js +1 -0
- package/out/chunk-VQJCXGIY.js +7 -0
- package/out/chunk-W4J3MGLB.js +1 -0
- package/out/chunk-WGG7KQUH.js +1 -0
- package/out/chunk-WZDTZE64.js +1 -0
- package/out/chunk-XL35ZV6R.js +1 -0
- package/out/chunk-XYFXXB2G.js +10 -0
- package/out/chunk-YVZH5SHP.js +1 -0
- package/out/chunk-ZBBOBQ43.js +1 -0
- package/out/chunk-ZMQQCGF6.js +2 -0
- package/out/client-managed-import.js +4 -0
- package/out/client-managed.js +37 -0
- package/out/client-sync.js +10 -13
- package/out/github-issue-authorized.html +3 -0
- package/out/github-issue-authorized.js +1 -0
- package/out/graph.js +17 -4
- package/out/index.html +90 -8
- package/out/prism.js +6 -2
- package/out/stasis.svg +20 -0
- package/out/terminal.js +365 -39
- package/out/view.css +1 -1
- package/out/view.js +83 -117
- package/package.json +298 -59
- package/risk/files/characters.js +196 -0
- package/risk/files/hosts.js +205 -0
- package/risk/files/readability.js +171 -0
- package/risk/files/runs-code.js +595 -0
- package/risk/files/script.js +114 -0
- package/risk/files/stamps.js +46 -0
- package/risk/index.d.ts +156 -0
- package/risk/index.js +7 -0
- package/risk/npm/assess.js +223 -0
- package/risk/npm/combined.js +65 -0
- package/risk/npm/compare.js +228 -0
- package/risk/npm/dependencies.js +153 -0
- package/risk/npm/diff.js +43 -0
- package/risk/npm/downloads.js +84 -0
- package/risk/npm/files.js +34 -0
- package/risk/npm/held.js +60 -0
- package/risk/npm/install-scripts.js +34 -0
- package/risk/npm/malware.js +36 -0
- package/risk/npm/manifest.js +65 -0
- package/risk/npm/new-dependency.js +30 -0
- package/risk/npm/old-version.js +108 -0
- package/risk/npm/registry.js +282 -0
- package/risk/npm/release.js +85 -0
- package/risk/npm/score.js +59 -0
- package/risk/npm/specs.js +124 -0
- package/risk/npm/tarball.js +113 -0
- package/server-common/database-config.ts +16 -0
- package/server-common/initialize.ts +18 -0
- package/server-common/npm-advisories.ts +101 -0
- package/{server → server-common}/origin.ts +5 -5
- package/server-common/reap.ts +48 -0
- package/server-common/scan-config.ts +19 -0
- package/server-common/standalone.ts +29 -0
- package/server-common/storage-crypto.ts +182 -0
- package/server-common/storage-log.ts +38 -0
- package/server-common/vercel-blob.ts +103 -0
- package/server-e2e/app.ts +486 -0
- package/{server → server-e2e}/auth.ts +5 -1
- package/{server → server-e2e}/bus-receiver.ts +2 -1
- package/{server → server-e2e}/cli.js +9 -4
- package/{server → server-e2e}/config.ts +56 -35
- package/{server → server-e2e}/db-neon.ts +2 -2
- package/{server → server-e2e}/db-revision-sql.ts +1 -1
- package/{server → server-e2e}/db-stmt.ts +2 -2
- package/{server → server-e2e}/db.ts +7 -7
- package/{server → server-e2e}/http.ts +116 -18
- package/{server → server-e2e}/hub.ts +40 -9
- package/server-e2e/index.ts +17 -0
- package/server-e2e/lifecycle.ts +95 -0
- package/{server → server-e2e}/neon-driver.ts +2 -2
- package/{server → server-e2e}/npm-proxy.ts +12 -145
- package/{server → server-e2e}/objstore/blob-vercel.ts +10 -114
- package/{server → server-e2e}/objstore/blob.ts +1 -1
- package/server-e2e/objstore/fetch-mint-guard.ts +74 -0
- package/{server → server-e2e}/objstore/handlers.ts +9 -8
- package/{server → server-e2e}/objstore/init.ts +35 -18
- package/{server → server-e2e}/objstore/reaper.ts +1 -1
- package/server-e2e/objstore/rest-deny.ts +28 -0
- package/server-e2e/objstore/rest-mint.ts +224 -0
- package/{server → server-e2e}/objstore/rest.ts +27 -26
- package/{server → server-e2e}/objstore/sign.ts +105 -0
- package/{server → server-e2e}/objstore/store-neon.ts +6 -10
- package/{server → server-e2e}/objstore/store.ts +7 -7
- package/{server → server-e2e}/objstore/tokens.ts +2 -2
- package/{server → server-e2e}/pubsub.ts +12 -9
- package/{server → server-e2e}/sign.ts +4 -4
- package/{server → server-e2e}/sse-server.ts +102 -68
- package/{server → server-e2e}/sse-session.ts +28 -8
- package/{server → server-e2e}/static.ts +31 -21
- package/server-e2e/sync-handlers.ts +408 -0
- package/{server → server-e2e}/ws-server.ts +20 -9
- package/server-managed/activity.ts +245 -0
- package/server-managed/avatar-store.ts +12 -0
- package/server-managed/blob-store.ts +17 -0
- package/server-managed/brotli.ts +10 -0
- package/server-managed/bundle-advisories.ts +120 -0
- package/server-managed/bundle-advisory-inventory.ts +77 -0
- package/server-managed/bundle-build-diagnostics.d.ts +10 -0
- package/server-managed/bundle-build-diagnostics.js +23 -0
- package/server-managed/bundle-build-leases.ts +41 -0
- package/server-managed/bundle-build-worker.js +111 -0
- package/server-managed/bundle-build.ts +198 -0
- package/server-managed/bundle-cache.ts +199 -0
- package/server-managed/bundle-catalog.ts +29 -0
- package/server-managed/bundle-commits.ts +140 -0
- package/server-managed/bundle-store.ts +24 -0
- package/server-managed/bundle-summary-cache.ts +130 -0
- package/server-managed/bundle.ts +120 -0
- package/server-managed/cache-storage.ts +19 -0
- package/server-managed/cli.js +21 -0
- package/server-managed/combined.ts +46 -0
- package/server-managed/comments.ts +151 -0
- package/server-managed/config.ts +158 -0
- package/server-managed/content-access.ts +15 -0
- package/server-managed/crypto.ts +25 -0
- package/server-managed/db-methods.ts +1725 -0
- package/server-managed/db-neon.ts +367 -0
- package/server-managed/db-schema.ts +227 -0
- package/server-managed/db-table-names.ts +22 -0
- package/server-managed/db.ts +132 -0
- package/server-managed/dependency-reviews.ts +248 -0
- package/server-managed/github-app.ts +391 -0
- package/server-managed/github-errors.ts +68 -0
- package/server-managed/github-issue-links.ts +127 -0
- package/server-managed/github-issue-oauth.ts +47 -0
- package/server-managed/github-issues.ts +152 -0
- package/server-managed/github-metadata.ts +213 -0
- package/server-managed/github-oauth.ts +235 -0
- package/server-managed/github-pulls.ts +227 -0
- package/server-managed/http-response.ts +50 -0
- package/server-managed/http.ts +3472 -0
- package/server-managed/import-triage.ts +51 -0
- package/server-managed/index.ts +187 -0
- package/server-managed/kept.ts +28 -0
- package/server-managed/link-reports.ts +158 -0
- package/server-managed/locked-packages.ts +85 -0
- package/server-managed/lru.ts +30 -0
- package/server-managed/managed-issues.ts +75 -0
- package/server-managed/management-catalog.ts +45 -0
- package/server-managed/management.ts +99 -0
- package/server-managed/npm-insights.ts +440 -0
- package/server-managed/npm-kept.ts +65 -0
- package/server-managed/npm-loads.ts +167 -0
- package/server-managed/npm-manifest.ts +115 -0
- package/server-managed/npm-packages.ts +378 -0
- package/server-managed/npm-provenance.ts +123 -0
- package/server-managed/npm-risk.ts +177 -0
- package/server-managed/object-storage-disk.ts +148 -0
- package/server-managed/object-storage-vercel.ts +67 -0
- package/server-managed/object-storage.ts +74 -0
- package/server-managed/package-entry-points.ts +51 -0
- package/server-managed/pretty-print.ts +352 -0
- package/server-managed/public-workspace.ts +220 -0
- package/server-managed/rename-diff-worker.js +26 -0
- package/server-managed/rename-diff.ts +270 -0
- package/server-managed/repo-path.ts +21 -0
- package/server-managed/report-migration.ts +35 -0
- package/server-managed/report-query.ts +10 -0
- package/server-managed/report-response.ts +16 -0
- package/server-managed/report-sources.ts +178 -0
- package/server-managed/report-store.ts +47 -0
- package/server-managed/repository-aliases.ts +91 -0
- package/server-managed/repository-browser.ts +153 -0
- package/server-managed/repository-discovery.ts +82 -0
- package/server-managed/repository-policy.ts +27 -0
- package/server-managed/repository-risk.ts +420 -0
- package/server-managed/revisions.ts +35 -0
- package/server-managed/session.ts +92 -0
- package/server-managed/slugs.ts +38 -0
- package/server-managed/solidity-entry-points.ts +69 -0
- package/server-managed/sql-postgres.ts +31 -0
- package/server-managed/sql.ts +76 -0
- package/server-managed/static.ts +28 -0
- package/server-managed/storage-command.ts +16 -0
- package/server-managed/storage-db.ts +175 -0
- package/server-managed/storage-encryption.ts +279 -0
- package/server-managed/storage-maintenance.ts +256 -0
- package/server-managed/storage-payload.ts +103 -0
- package/server-managed/storage-stores.ts +85 -0
- package/server-managed/storage.ts +78 -0
- package/server-managed/team-app.ts +94 -0
- package/server-managed/team-catalog.ts +7 -0
- package/server-managed/team-feed.ts +173 -0
- package/server-managed/team-npm-scopes.ts +77 -0
- package/server-managed/team-reports.ts +228 -0
- package/server-managed/triage-response.ts +16 -0
- package/server-managed/type-only-worker.js +19 -0
- package/server-managed/type-only.ts +103 -0
- package/server-managed/uploads.ts +86 -0
- package/server-managed/upstream-cache.ts +215 -0
- package/server-managed/view-as.ts +58 -0
- package/server-managed/workspace-shares.ts +166 -0
- package/server.ts +50 -0
- package/server/index.ts +0 -477
- package/server/lifecycle.ts +0 -204
- package/server/sync-handlers.ts +0 -320
- /package/{LICENSE → LICENSE-MIT} +0 -0
- /package/{server → server-e2e}/config.example.json +0 -0
- /package/{server → server-e2e}/objstore/blob-fs.ts +0 -0
- /package/{server → server-e2e}/objstore/fs.ts +0 -0
- /package/{server → server-e2e}/peer.ts +0 -0
- /package/{server → server-e2e}/util.ts +0 -0
- /package/{server → server-e2e}/validation.ts +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Managed-server boot config. GitHub user authorization establishes identity;
|
|
2
|
+
// optional App installation credentials enable repository access. A single
|
|
3
|
+
// GitHub App can provide both flows, with repository grants at installation.
|
|
4
|
+
import { env } from 'node:process'
|
|
5
|
+
import { databaseUrls } from '../server-common/database-config.ts'
|
|
6
|
+
import { MAX_UPLOAD_BYTES } from './uploads.ts'
|
|
7
|
+
import { parseStorageKey } from '../server-common/storage-crypto.ts'
|
|
8
|
+
import { defaultCacheDir } from '@preventive/upstream/npm.js'
|
|
9
|
+
import { RESERVED_COOKIES } from './session.ts'
|
|
10
|
+
|
|
11
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost'])
|
|
12
|
+
|
|
13
|
+
export interface ManagedConfig {
|
|
14
|
+
port: number
|
|
15
|
+
host: string
|
|
16
|
+
dbPath: string
|
|
17
|
+
neonUrl?: string | null
|
|
18
|
+
blobToken?: string | null
|
|
19
|
+
storageEncryptionKey?: string | null
|
|
20
|
+
storageEncryptionMigrate?: boolean
|
|
21
|
+
storageEncryptionMigrateMaxMs?: number
|
|
22
|
+
vercelPreview?: boolean
|
|
23
|
+
serverless?: boolean
|
|
24
|
+
// Upstream's disk cache (setCacheDir) for audits and bundle builds: its default
|
|
25
|
+
// location, or null for none, as on Vercel, where the database keeps listings.
|
|
26
|
+
upstreamCacheDir?: string | null
|
|
27
|
+
debug: boolean
|
|
28
|
+
allowShare: boolean
|
|
29
|
+
trustProxyEnv: string | undefined
|
|
30
|
+
// GitHub App user-authorization (identity) credentials — the App's client id
|
|
31
|
+
// + secret, used by the login flow.
|
|
32
|
+
githubClientId: string
|
|
33
|
+
githubClientSecret: string
|
|
34
|
+
// Preapproved GitHub identity promoted on login when it is the only user
|
|
35
|
+
// and its role is No access, including a login after registration.
|
|
36
|
+
initialAdminGithubId: number | null
|
|
37
|
+
// Absolute callback registered with GitHub, e.g.
|
|
38
|
+
// 'https://triage.example.com/api/oauth/github/callback'.
|
|
39
|
+
oauthCallbackUrl: string
|
|
40
|
+
// Whether cookies carry `Secure` (callback is https). Also gates the
|
|
41
|
+
// `__Host-` prefix, so loopback http dev can run with a plain cookie name.
|
|
42
|
+
cookieSecure: boolean
|
|
43
|
+
sessionCookieName: string
|
|
44
|
+
sessionTtlMs: number
|
|
45
|
+
// Optional installation credentials for the same GitHub App as login.
|
|
46
|
+
// Repository permissions are approved when connecting repositories.
|
|
47
|
+
githubAppId: string | null
|
|
48
|
+
githubAppPrivateKey: string | null
|
|
49
|
+
githubAppSlug: string | null
|
|
50
|
+
githubNewIssueLabels?: string
|
|
51
|
+
// Max accepted size (bytes) for an uploaded report on the "Manage reports"
|
|
52
|
+
// page, before storage compression (default 25 MiB).
|
|
53
|
+
maxReportBytes: number
|
|
54
|
+
// Max accepted size (bytes) for an uploaded bundle (sourcemap / stasis
|
|
55
|
+
// archive). Bundles run larger than reports, so a higher cap (default 200 MiB).
|
|
56
|
+
maxBundleBytes: number
|
|
57
|
+
// How many triage-trail events to keep per finding (managed_finding_triage_event):
|
|
58
|
+
// 0, the default, keeps everything — the trail is the record. An operator
|
|
59
|
+
// who would rather bound the store sets a positive count; older events of a
|
|
60
|
+
// finding are then trimmed as new ones land.
|
|
61
|
+
triageHistoryLimit: number
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function fail(msg: string): never {
|
|
65
|
+
throw new Error(msg)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function requireStr(name: string): string {
|
|
69
|
+
const v = env[name]
|
|
70
|
+
if (v == null || v === '') fail(`Missing required env ${name} (managed mode).`)
|
|
71
|
+
return v
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function intEnv(name: string, def: number, min: number, max: number): number {
|
|
75
|
+
const raw = env[name]
|
|
76
|
+
const n = raw == null ? def : Number(raw)
|
|
77
|
+
if (!Number.isSafeInteger(n) || n < min || n > max) {
|
|
78
|
+
fail(`Invalid ${name}: ${raw} — must be an integer in [${min}, ${max}].`)
|
|
79
|
+
}
|
|
80
|
+
return n
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function optionalGithubId(name: string): number | null {
|
|
84
|
+
const raw = env[name]
|
|
85
|
+
if (raw == null || raw === '') return null
|
|
86
|
+
const id = Number(raw)
|
|
87
|
+
if (!/^[1-9]\d*$/u.test(raw) || !Number.isSafeInteger(id)) {
|
|
88
|
+
fail(`Invalid ${name}: must be a single positive numeric GitHub user ID.`)
|
|
89
|
+
}
|
|
90
|
+
return id
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function urlOrFail(name: string, raw: string): URL {
|
|
94
|
+
try { return new URL(raw) } catch { fail(`${name} is not a valid URL: ${raw}`) }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function loadManagedConfig({ combined = false } = {}): ManagedConfig {
|
|
98
|
+
const serverless = env['VERCEL'] === '1'
|
|
99
|
+
const neonUrl = databaseUrls({ combined }).managed
|
|
100
|
+
const blobToken = env['BLOB_READ_WRITE_TOKEN'] || null
|
|
101
|
+
const storageEncryptionKey = env['MANAGED_STORAGE_ENCRYPTION_KEY'] || null
|
|
102
|
+
parseStorageKey(storageEncryptionKey)
|
|
103
|
+
const storageEncryptionMigrate = env['MANAGED_STORAGE_ENCRYPTION_MIGRATE'] === '1'
|
|
104
|
+
if (storageEncryptionMigrate && !storageEncryptionKey) fail('MANAGED_STORAGE_ENCRYPTION_MIGRATE requires MANAGED_STORAGE_ENCRYPTION_KEY.')
|
|
105
|
+
if (serverless && !neonUrl) fail('Vercel managed mode requires DATABASE_URL or MANAGED_DATABASE_URL.')
|
|
106
|
+
if (neonUrl && !blobToken) fail('Managed Neon mode requires BLOB_READ_WRITE_TOKEN.')
|
|
107
|
+
const host = env['HOST'] ?? '127.0.0.1'
|
|
108
|
+
const oauthCallbackUrl = requireStr('OAUTH_CALLBACK_URL')
|
|
109
|
+
const callback = urlOrFail('OAUTH_CALLBACK_URL', oauthCallbackUrl)
|
|
110
|
+
const cookieSecure = callback.protocol === 'https:'
|
|
111
|
+
// A `__Host-` cookie mandates `Secure`, so any non-loopback bind must be
|
|
112
|
+
// HTTPS — fail fast (mirrors server-e2e's boot check). Loopback dev over
|
|
113
|
+
// http is allowed with a non-prefixed cookie name.
|
|
114
|
+
if ((serverless || !LOOPBACK_HOSTS.has(host)) && !cookieSecure) {
|
|
115
|
+
fail(`Vercel or non-loopback HOST=${host} requires an https OAUTH_CALLBACK_URL — the session cookie needs Secure.`)
|
|
116
|
+
}
|
|
117
|
+
const sessionCookieName = env['SESSION_COOKIE_NAME'] ?? '__Host-dvsid'
|
|
118
|
+
if (sessionCookieName.startsWith('__Host-') && !cookieSecure) {
|
|
119
|
+
fail(`SESSION_COOKIE_NAME=${sessionCookieName} uses the __Host- prefix but the callback is not https. Use a non-prefixed name for loopback http dev.`)
|
|
120
|
+
}
|
|
121
|
+
if (RESERVED_COOKIES.includes(sessionCookieName.replace(/^__Host-/u, ''))) {
|
|
122
|
+
fail(`SESSION_COOKIE_NAME=${sessionCookieName} is reserved for another managed cookie. Choose a different name.`)
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
neonUrl, blobToken, serverless, storageEncryptionKey, storageEncryptionMigrate,
|
|
126
|
+
storageEncryptionMigrateMaxMs: intEnv('MANAGED_STORAGE_ENCRYPTION_MIGRATE_MAX_MS', 150_000, 1, serverless ? 240_000 : 3_600_000),
|
|
127
|
+
vercelPreview: env['VERCEL_ENV'] === 'preview',
|
|
128
|
+
upstreamCacheDir: serverless ? null : defaultCacheDir ?? null,
|
|
129
|
+
port: intEnv('PORT', 8765, 0, 65535),
|
|
130
|
+
host,
|
|
131
|
+
// DB_PATH belongs to e2e in a combined process. Keep the two stores apart.
|
|
132
|
+
dbPath: env['MANAGED_DB_PATH'] ?? (combined ? undefined : env['DB_PATH']) ?? 'server-managed/data/managed.db',
|
|
133
|
+
debug: env['DEBUG'] === '1' || env['DEBUG'] === 'true',
|
|
134
|
+
allowShare: env['DEEPVIEW_ALLOW_SHARE'] === '1',
|
|
135
|
+
trustProxyEnv: env['TRUST_PROXY'] ?? (serverless ? '1' : undefined),
|
|
136
|
+
githubClientId: requireStr('GITHUB_CLIENT_ID'),
|
|
137
|
+
githubClientSecret: requireStr('GITHUB_CLIENT_SECRET'),
|
|
138
|
+
initialAdminGithubId: optionalGithubId('MANAGED_INITIAL_ADMIN_GITHUB_ID'),
|
|
139
|
+
oauthCallbackUrl,
|
|
140
|
+
cookieSecure,
|
|
141
|
+
sessionCookieName,
|
|
142
|
+
sessionTtlMs: intEnv('SESSION_TTL_MS', 1_209_600_000, 60_000, 7_776_000_000),
|
|
143
|
+
githubAppId: env['GITHUB_APP_ID'] ?? null,
|
|
144
|
+
githubAppPrivateKey: normalizePem(env['GITHUB_APP_PRIVATE_KEY']),
|
|
145
|
+
githubAppSlug: env['GITHUB_APP_SLUG'] ?? null,
|
|
146
|
+
githubNewIssueLabels: env['GITHUB_NEW_ISSUE_LABELS'] ?? '',
|
|
147
|
+
maxReportBytes: intEnv('MAX_REPORT_BYTES', 26_214_400, 1, 104_857_600),
|
|
148
|
+
maxBundleBytes: intEnv('MAX_BUNDLE_BYTES', 209_715_200, 1, MAX_UPLOAD_BYTES),
|
|
149
|
+
triageHistoryLimit: intEnv('TRIAGE_HISTORY_LIMIT', 0, 0, 1_000_000_000),
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// PEM private keys are awkward in env vars; accept a literal multi-line value or
|
|
154
|
+
// one with escaped newlines (`\n`). Empty/absent → null (private repos off).
|
|
155
|
+
function normalizePem(raw: string | undefined): string | null {
|
|
156
|
+
if (raw == null || raw === '') return null
|
|
157
|
+
return raw.includes('\\n') ? raw.replaceAll('\\n', '\n') : raw
|
|
158
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ManagedDb, StoredUser } from './db.ts'
|
|
2
|
+
|
|
3
|
+
export type RepoScope = { repoId: number; path: string | null }
|
|
4
|
+
type Content = { repoId: number | null; repoDirectory?: string }
|
|
5
|
+
|
|
6
|
+
// Read grants for each request: neither the manager role nor a cached page
|
|
7
|
+
// confers repository access. Bundles have repository scope; reports also have
|
|
8
|
+
// a directory scope. Unassigned content is only available to administrators.
|
|
9
|
+
export async function contentAccess(db: Pick<ManagedDb, 'listRepoScopesForUser'>, user: StoredUser) {
|
|
10
|
+
const scopes = user.role === 'admin' ? null : await db.listRepoScopesForUser(user.id)
|
|
11
|
+
const bundle = (item: Content) => scopes == null || scopes.some(scope => scope.repoId === item.repoId)
|
|
12
|
+
const report = (item: Content) => scopes == null || scopes.some(scope => scope.repoId === item.repoId
|
|
13
|
+
&& (!scope.path || item.repoDirectory === scope.path || item.repoDirectory?.startsWith(scope.path + '/')))
|
|
14
|
+
return { scopes, bundle, report }
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Token helpers for the managed auth server. The raw session token lives ONLY
|
|
2
|
+
// in the cookie; the DB row id is its SHA-256 (see db.ts / session.ts), so a
|
|
3
|
+
// DB read can't reconstruct a live cookie. No HMAC pepper is needed — the
|
|
4
|
+
// tokens are 256-bit random, not guessable or reversible from their hash.
|
|
5
|
+
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto'
|
|
6
|
+
|
|
7
|
+
// 256-bit URL-safe random token: the session cookie value and the OAuth CSRF
|
|
8
|
+
// `state` nonce.
|
|
9
|
+
export function randomToken(): string {
|
|
10
|
+
return randomBytes(32).toString('base64url')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// At-rest id for a session cookie token (stored as the managed_session PK).
|
|
14
|
+
export function hashToken(token: string): string {
|
|
15
|
+
return createHash('sha256').update(token, 'utf8').digest('base64url')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Constant-time equality for CSRF / OAuth-state checks. A length mismatch
|
|
19
|
+
// short-circuits (the length of these fixed-width tokens isn't a secret).
|
|
20
|
+
export function safeEqual(a: string, b: string): boolean {
|
|
21
|
+
const ab = Buffer.from(a, 'utf8')
|
|
22
|
+
const bb = Buffer.from(b, 'utf8')
|
|
23
|
+
if (ab.length !== bb.length) return false
|
|
24
|
+
return timingSafeEqual(ab, bb)
|
|
25
|
+
}
|