@shiftleftpt/sbd-toe-mcp 0.1.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.
Files changed (93) hide show
  1. package/.env.example +35 -0
  2. package/LICENSE +201 -0
  3. package/README.md +323 -0
  4. package/data/publish/algolia_docs_records.json +148847 -0
  5. package/data/publish/algolia_docs_records_enriched.json +194004 -0
  6. package/data/publish/algolia_entities_records.json +74715 -0
  7. package/data/publish/algolia_entities_records_enriched.json +177587 -0
  8. package/data/publish/algolia_index_settings.json +102 -0
  9. package/data/publish/sbd-toe-index-compact.json +111 -0
  10. package/data/reports/run_manifest.json +10 -0
  11. package/dist/backend/semantic-index-gateway.d.ts +25 -0
  12. package/dist/backend/semantic-index-gateway.js +555 -0
  13. package/dist/backend/semantic-index-gateway.js.map +1 -0
  14. package/dist/backend/semantic-index-gateway.test.d.ts +1 -0
  15. package/dist/backend/semantic-index-gateway.test.js +384 -0
  16. package/dist/backend/semantic-index-gateway.test.js.map +1 -0
  17. package/dist/bootstrap/checkout-backend.d.ts +31 -0
  18. package/dist/bootstrap/checkout-backend.js +136 -0
  19. package/dist/bootstrap/checkout-backend.js.map +1 -0
  20. package/dist/bootstrap/checkout-backend.test.d.ts +1 -0
  21. package/dist/bootstrap/checkout-backend.test.js +158 -0
  22. package/dist/bootstrap/checkout-backend.test.js.map +1 -0
  23. package/dist/bootstrap/release-checkout.d.ts +8 -0
  24. package/dist/bootstrap/release-checkout.js +168 -0
  25. package/dist/bootstrap/release-checkout.js.map +1 -0
  26. package/dist/bootstrap/release-checkout.test.d.ts +1 -0
  27. package/dist/bootstrap/release-checkout.test.js +137 -0
  28. package/dist/bootstrap/release-checkout.test.js.map +1 -0
  29. package/dist/config.d.ts +4 -0
  30. package/dist/config.js +81 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.js +1063 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/orchestrator/ask-manual.d.ts +13 -0
  36. package/dist/orchestrator/ask-manual.js +202 -0
  37. package/dist/orchestrator/ask-manual.js.map +1 -0
  38. package/dist/prompt/build-answer-prompt.d.ts +2 -0
  39. package/dist/prompt/build-answer-prompt.js +51 -0
  40. package/dist/prompt/build-answer-prompt.js.map +1 -0
  41. package/dist/prompt/system-prompt.d.ts +1 -0
  42. package/dist/prompt/system-prompt.js +94 -0
  43. package/dist/prompt/system-prompt.js.map +1 -0
  44. package/dist/resources/sbd-toe-resources.d.ts +18 -0
  45. package/dist/resources/sbd-toe-resources.js +164 -0
  46. package/dist/resources/sbd-toe-resources.js.map +1 -0
  47. package/dist/resources/sbd-toe-resources.test.d.ts +1 -0
  48. package/dist/resources/sbd-toe-resources.test.js +134 -0
  49. package/dist/resources/sbd-toe-resources.test.js.map +1 -0
  50. package/dist/test-utils.d.ts +153 -0
  51. package/dist/test-utils.js +176 -0
  52. package/dist/test-utils.js.map +1 -0
  53. package/dist/tools/generate-document.d.ts +22 -0
  54. package/dist/tools/generate-document.js +392 -0
  55. package/dist/tools/generate-document.js.map +1 -0
  56. package/dist/tools/generate-document.test.d.ts +1 -0
  57. package/dist/tools/generate-document.test.js +189 -0
  58. package/dist/tools/generate-document.test.js.map +1 -0
  59. package/dist/tools/map-review-scope.d.ts +20 -0
  60. package/dist/tools/map-review-scope.js +299 -0
  61. package/dist/tools/map-review-scope.js.map +1 -0
  62. package/dist/tools/map-review-scope.test.d.ts +1 -0
  63. package/dist/tools/map-review-scope.test.js +204 -0
  64. package/dist/tools/map-review-scope.test.js.map +1 -0
  65. package/dist/tools/plan-repo-governance.d.ts +41 -0
  66. package/dist/tools/plan-repo-governance.js +509 -0
  67. package/dist/tools/plan-repo-governance.js.map +1 -0
  68. package/dist/tools/plan-repo-governance.test.d.ts +1 -0
  69. package/dist/tools/plan-repo-governance.test.js +237 -0
  70. package/dist/tools/plan-repo-governance.test.js.map +1 -0
  71. package/dist/tools/structured-tools.d.ts +5 -0
  72. package/dist/tools/structured-tools.js +310 -0
  73. package/dist/tools/structured-tools.js.map +1 -0
  74. package/dist/tools/structured-tools.test.d.ts +1 -0
  75. package/dist/tools/structured-tools.test.js +459 -0
  76. package/dist/tools/structured-tools.test.js.map +1 -0
  77. package/dist/types.d.ts +160 -0
  78. package/dist/types.js +2 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/upstream/backend-contract.d.ts +3 -0
  81. package/dist/upstream/backend-contract.js +37 -0
  82. package/dist/upstream/backend-contract.js.map +1 -0
  83. package/dist/validators/ai-disclosure.d.ts +39 -0
  84. package/dist/validators/ai-disclosure.js +183 -0
  85. package/dist/validators/ai-disclosure.js.map +1 -0
  86. package/dist/validators/ai-disclosure.test.d.ts +1 -0
  87. package/dist/validators/ai-disclosure.test.js +244 -0
  88. package/dist/validators/ai-disclosure.test.js.map +1 -0
  89. package/examples/claude-desktop.json +8 -0
  90. package/examples/vscode.mcp.json +9 -0
  91. package/package.json +50 -0
  92. package/prompts/sbd-toe-chat-system.md +71 -0
  93. package/smithery.yaml +44 -0
@@ -0,0 +1,158 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { sanitizeRunManifest, ensurePublishedIndex } from "../bootstrap/checkout-backend.js";
3
+ // --- Tests ---
4
+ describe("checkout-backend.ts", () => {
5
+ describe("sanitizeRunManifest", () => {
6
+ it("preserves run_id when present", () => {
7
+ const upstream = {
8
+ run_id: "test-run-123"
9
+ };
10
+ const result = sanitizeRunManifest(upstream);
11
+ expect(result.run_id).toBe("test-run-123");
12
+ });
13
+ it("omits run_id when undefined", () => {
14
+ const upstream = {
15
+ generated_at: "2026-03-24T10:00:00Z"
16
+ };
17
+ const result = sanitizeRunManifest(upstream);
18
+ expect(result).not.toHaveProperty("run_id");
19
+ expect(result.generated_at).toBe("2026-03-24T10:00:00Z");
20
+ });
21
+ it("converts SSH repo_url to HTTPS", () => {
22
+ const upstream = {
23
+ repo_url: "git@github.com:test/repo.git"
24
+ };
25
+ const result = sanitizeRunManifest(upstream);
26
+ expect(result.repo_url).toBe("https://github.com/test/repo");
27
+ });
28
+ it("converts SSH repo_url without .git suffix", () => {
29
+ const upstream = {
30
+ repo_url: "git@github.com:test/repo"
31
+ };
32
+ const result = sanitizeRunManifest(upstream);
33
+ expect(result.repo_url).toBe("https://github.com/test/repo");
34
+ });
35
+ it("preserves HTTPS repo_url unchanged", () => {
36
+ const upstream = {
37
+ repo_url: "https://github.com/test/repo.git"
38
+ };
39
+ const result = sanitizeRunManifest(upstream);
40
+ expect(result.repo_url).toBe("https://github.com/test/repo.git");
41
+ });
42
+ it("handles whitespace in repo_url", () => {
43
+ const upstream = {
44
+ repo_url: " https://github.com/test/repo "
45
+ };
46
+ const result = sanitizeRunManifest(upstream);
47
+ expect(result.repo_url).toBe("https://github.com/test/repo");
48
+ });
49
+ it("omits repo_url when undefined", () => {
50
+ const upstream = {
51
+ run_id: "123"
52
+ };
53
+ const result = sanitizeRunManifest(upstream);
54
+ expect(result).not.toHaveProperty("repo_url");
55
+ });
56
+ it("omits repo_url when empty string", () => {
57
+ const upstream = {
58
+ repo_url: ""
59
+ };
60
+ const result = sanitizeRunManifest(upstream);
61
+ expect(result).not.toHaveProperty("repo_url");
62
+ });
63
+ it("preserves all fields when all present", () => {
64
+ const upstream = {
65
+ run_id: "run-001",
66
+ generated_at: "2026-03-24T10:00:00Z",
67
+ branch: "main",
68
+ commit_sha: "abc123",
69
+ corpus_root: "/corpus",
70
+ repo_url: "https://github.com/test/repo",
71
+ sync_mode: "full",
72
+ version: "1.0.0"
73
+ };
74
+ const result = sanitizeRunManifest(upstream);
75
+ expect(result.run_id).toBe("run-001");
76
+ expect(result.generated_at).toBe("2026-03-24T10:00:00Z");
77
+ expect(result.branch).toBe("main");
78
+ expect(result.commit_sha).toBe("abc123");
79
+ expect(result.corpus_root).toBe("/corpus");
80
+ expect(result.repo_url).toBe("https://github.com/test/repo");
81
+ expect(result.sync_mode).toBe("full");
82
+ expect(result.version).toBe("1.0.0");
83
+ });
84
+ });
85
+ describe("ensurePublishedIndex", () => {
86
+ it("finds index by record_family", () => {
87
+ const items = [
88
+ {
89
+ index_name: "test_docs",
90
+ record_family: "documents",
91
+ settings: { ranking: ["asc(popularity)"] }
92
+ }
93
+ ];
94
+ const result = ensurePublishedIndex(items, "documents", "default_docs");
95
+ expect(result.indexName).toBe("test_docs");
96
+ expect(result.recordFamily).toBe("documents");
97
+ expect(result.settings).toEqual({ ranking: ["asc(popularity)"] });
98
+ });
99
+ it("uses index_name as fallback when record_family not found", () => {
100
+ const items = [
101
+ {
102
+ index_name: "fallback_index",
103
+ record_family: "other_family"
104
+ }
105
+ ];
106
+ const result = ensurePublishedIndex(items, "entities", "fallback_index");
107
+ expect(result.indexName).toBe("fallback_index");
108
+ expect(result.recordFamily).toBe("entities");
109
+ });
110
+ it("throws when index not found by family or fallback", () => {
111
+ const items = [
112
+ {
113
+ index_name: "some_index",
114
+ record_family: "other_family"
115
+ }
116
+ ];
117
+ expect(() => {
118
+ ensurePublishedIndex(items, "documents", "missing_fallback");
119
+ }).toThrow(/O upstream não publicou um índice utilizável para "documents"/);
120
+ });
121
+ it("throws when items array is empty", () => {
122
+ expect(() => {
123
+ ensurePublishedIndex([], "documents", "fallback");
124
+ }).toThrow(/O upstream não publicou um índice utilizável/);
125
+ });
126
+ it("throws when items is undefined", () => {
127
+ expect(() => {
128
+ ensurePublishedIndex(undefined, "documents", "fallback");
129
+ }).toThrow(/O upstream não publicou um índice utilizável/);
130
+ });
131
+ it("defaults settings to empty object when not provided", () => {
132
+ const items = [
133
+ {
134
+ index_name: "test_index",
135
+ record_family: "documents"
136
+ // settings omitted
137
+ }
138
+ ];
139
+ const result = ensurePublishedIndex(items, "documents", "fallback");
140
+ expect(result.settings).toEqual({});
141
+ });
142
+ it("prefers exact family match over fallback", () => {
143
+ const items = [
144
+ {
145
+ index_name: "fallback_index",
146
+ record_family: "other_family"
147
+ },
148
+ {
149
+ index_name: "exact_docs_index",
150
+ record_family: "documents"
151
+ }
152
+ ];
153
+ const result = ensurePublishedIndex(items, "documents", "fallback_index");
154
+ expect(result.indexName).toBe("exact_docs_index");
155
+ });
156
+ });
157
+ });
158
+ //# sourceMappingURL=checkout-backend.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout-backend.test.js","sourceRoot":"","sources":["../../src/bootstrap/checkout-backend.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AppConfig } from "../types.js";
2
+ export declare function assertSafeAssetUrl(url: string): void;
3
+ export declare function assertSafeDestPath(destPath: string, baseDir: string): void;
4
+ export declare function fetchReleaseAssetUrl(tag: string, timeoutMs: number): Promise<{
5
+ assetUrl: string;
6
+ assetName: string;
7
+ }>;
8
+ export declare function checkoutFromRelease(config: AppConfig, destDir: string): Promise<void>;
@@ -0,0 +1,168 @@
1
+ import { createWriteStream } from "node:fs";
2
+ import { copyFile, mkdir, mkdtemp, rm } from "node:fs/promises";
3
+ import { Readable } from "node:stream";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { pipeline } from "node:stream/promises";
7
+ import { spawnSync } from "node:child_process";
8
+ // SECURITY: URL base e owner/repo são HARDCODED. Nunca aceitar de env ou input externo.
9
+ const HARDCODED_API_BASE = "https://api.github.com/repos/Shiftleftpt/sbd-toe-knowledge-graph";
10
+ const ALLOWED_ASSET_URL_PREFIXES = [
11
+ "https://github.com/Shiftleftpt/sbd-toe-knowledge-graph/",
12
+ "https://objects.githubusercontent.com/",
13
+ ];
14
+ // Fixed list of files to copy from the extracted bundle to destDir.
15
+ // SECURITY: Only known paths are copied; no dynamic traversal of extracted content.
16
+ const KNOWN_FILES = [
17
+ {
18
+ src: path.join("data", "publish", "algolia_docs_records.json"),
19
+ dest: path.join("data", "publish", "algolia_docs_records.json"),
20
+ },
21
+ {
22
+ src: path.join("data", "publish", "algolia_entities_records.json"),
23
+ dest: path.join("data", "publish", "algolia_entities_records.json"),
24
+ },
25
+ {
26
+ src: path.join("data", "publish", "algolia_docs_records_enriched.json"),
27
+ dest: path.join("data", "publish", "algolia_docs_records_enriched.json"),
28
+ },
29
+ {
30
+ src: path.join("data", "publish", "algolia_entities_records_enriched.json"),
31
+ dest: path.join("data", "publish", "algolia_entities_records_enriched.json"),
32
+ },
33
+ {
34
+ src: path.join("data", "publish", "algolia_index_settings.json"),
35
+ dest: path.join("data", "publish", "algolia_index_settings.json"),
36
+ },
37
+ {
38
+ src: path.join("data", "reports", "run_manifest.json"),
39
+ dest: path.join("data", "reports", "run_manifest.json"),
40
+ },
41
+ ];
42
+ export function assertSafeAssetUrl(url) {
43
+ const allowed = ALLOWED_ASSET_URL_PREFIXES.some((prefix) => url.startsWith(prefix));
44
+ if (!allowed) {
45
+ throw new Error(`URL de asset não autorizada: ${url}`);
46
+ }
47
+ }
48
+ export function assertSafeDestPath(destPath, baseDir) {
49
+ const resolved = path.resolve(destPath);
50
+ const base = path.resolve(baseDir);
51
+ if (!resolved.startsWith(base + path.sep) && resolved !== base) {
52
+ throw new Error(`Path traversal detectado: ${destPath}`);
53
+ }
54
+ }
55
+ export async function fetchReleaseAssetUrl(tag, timeoutMs) {
56
+ const controller = new AbortController();
57
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
58
+ try {
59
+ const releaseUrl = tag === "latest"
60
+ ? `${HARDCODED_API_BASE}/releases/latest`
61
+ : `${HARDCODED_API_BASE}/releases/tags/${encodeURIComponent(tag)}`;
62
+ const resp = await fetch(releaseUrl, {
63
+ signal: controller.signal,
64
+ headers: {
65
+ Accept: "application/vnd.github+json",
66
+ "X-GitHub-Api-Version": "2022-11-28",
67
+ },
68
+ });
69
+ if (!resp.ok) {
70
+ throw new Error(`GitHub API respondeu ${resp.status} para ${releaseUrl}`);
71
+ }
72
+ const release = (await resp.json());
73
+ const asset = release.assets?.find((a) => a.name.endsWith(".tar.gz") ||
74
+ a.name.endsWith(".zip") ||
75
+ a.name.includes("bundle"));
76
+ if (!asset) {
77
+ throw new Error(`Nenhum asset de bundle encontrado na release '${tag}'.`);
78
+ }
79
+ assertSafeAssetUrl(asset.browser_download_url);
80
+ return { assetUrl: asset.browser_download_url, assetName: asset.name };
81
+ }
82
+ finally {
83
+ clearTimeout(timer);
84
+ }
85
+ }
86
+ export async function checkoutFromRelease(config, destDir) {
87
+ const { upstreamReleaseTag, upstreamReleaseMaxBytes, upstreamReleaseTimeoutMs } = config.backend;
88
+ const { assetUrl, assetName } = await fetchReleaseAssetUrl(upstreamReleaseTag, upstreamReleaseTimeoutMs);
89
+ process.stderr.write(`[release-checkout] Downloading asset '${assetName}' from release '${upstreamReleaseTag}'.\n`);
90
+ // Download with timeout and size limit
91
+ const controller = new AbortController();
92
+ const timer = setTimeout(() => controller.abort(), upstreamReleaseTimeoutMs);
93
+ let tmpDir;
94
+ let tmpFile;
95
+ try {
96
+ const resp = await fetch(assetUrl, { signal: controller.signal });
97
+ if (!resp.ok || !resp.body) {
98
+ throw new Error(`Download falhou com status ${resp.status} para ${assetUrl}`);
99
+ }
100
+ tmpDir = await mkdtemp(path.join(os.tmpdir(), "sbd-release-"));
101
+ tmpFile = path.join(tmpDir, assetName);
102
+ let bytesReceived = 0;
103
+ const fileStream = createWriteStream(tmpFile);
104
+ await pipeline(Readable.fromWeb(resp.body), async function* (source) {
105
+ for await (const chunk of source) {
106
+ bytesReceived += chunk.length;
107
+ if (bytesReceived > upstreamReleaseMaxBytes) {
108
+ throw new Error(`Asset excede o limite de tamanho (${upstreamReleaseMaxBytes} bytes): ${assetName}`);
109
+ }
110
+ yield chunk;
111
+ }
112
+ }, fileStream);
113
+ // Extract
114
+ const extractDir = path.join(tmpDir, "extracted");
115
+ await mkdir(extractDir, { recursive: true });
116
+ if (assetName.endsWith(".tar.gz") || assetName.endsWith(".tgz")) {
117
+ // SECURITY: argv fixos, sem shell, sem interpolação de env
118
+ const result = spawnSync("tar", ["-xzf", tmpFile, "-C", extractDir], {
119
+ stdio: ["ignore", "ignore", "pipe"],
120
+ timeout: upstreamReleaseTimeoutMs,
121
+ shell: false,
122
+ });
123
+ if (result.status !== 0) {
124
+ const stderr = result.stderr instanceof Buffer ? result.stderr.toString() : "";
125
+ throw new Error(`Extracção tar falhou (status ${result.status ?? "?"}): ${stderr.trim()}`);
126
+ }
127
+ }
128
+ else if (assetName.endsWith(".zip")) {
129
+ // SECURITY: argv fixos, sem shell, sem interpolação de env
130
+ const result = spawnSync("unzip", ["-q", tmpFile, "-d", extractDir], {
131
+ stdio: ["ignore", "ignore", "pipe"],
132
+ timeout: upstreamReleaseTimeoutMs,
133
+ shell: false,
134
+ });
135
+ if (result.status !== 0) {
136
+ const stderr = result.stderr instanceof Buffer ? result.stderr.toString() : "";
137
+ throw new Error(`Extracção zip falhou (status ${result.status ?? "?"}): ${stderr.trim()}`);
138
+ }
139
+ }
140
+ else {
141
+ throw new Error(`Formato de asset não suportado: ${assetName}`);
142
+ }
143
+ // Copy known files from extracted bundle to destDir
144
+ for (const { src, dest } of KNOWN_FILES) {
145
+ const srcPath = path.join(extractDir, src);
146
+ const destPath = path.join(destDir, dest);
147
+ // SECURITY: validate that the destination stays within destDir
148
+ assertSafeDestPath(destPath, destDir);
149
+ await mkdir(path.dirname(destPath), { recursive: true });
150
+ try {
151
+ await copyFile(srcPath, destPath);
152
+ process.stderr.write(`[release-checkout] Copiado: ${dest}\n`);
153
+ }
154
+ catch (err) {
155
+ const message = err instanceof Error ? err.message : String(err);
156
+ process.stderr.write(`[release-checkout] AVISO: ficheiro não encontrado no bundle: ${src} (${message})\n`);
157
+ }
158
+ }
159
+ process.stderr.write(`[release-checkout] Checkout via release '${upstreamReleaseTag}' concluído.\n`);
160
+ }
161
+ finally {
162
+ clearTimeout(timer);
163
+ if (tmpDir) {
164
+ await rm(tmpDir, { recursive: true, force: true }).catch(() => undefined);
165
+ }
166
+ }
167
+ }
168
+ //# sourceMappingURL=release-checkout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-checkout.js","sourceRoot":"","sources":["../../src/bootstrap/release-checkout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,137 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import path from "node:path";
3
+ import { assertSafeAssetUrl, assertSafeDestPath, fetchReleaseAssetUrl, } from "./release-checkout.js";
4
+ // ---------------------------------------------------------------------------
5
+ // assertSafeAssetUrl
6
+ // ---------------------------------------------------------------------------
7
+ describe("assertSafeAssetUrl", () => {
8
+ it("accepts an authorised github.com URL", () => {
9
+ expect(() => assertSafeAssetUrl("https://github.com/Shiftleftpt/sbd-toe-knowledge-graph/releases/download/v1.0.0/bundle.tar.gz")).not.toThrow();
10
+ });
11
+ it("accepts an authorised objects.githubusercontent.com URL", () => {
12
+ expect(() => assertSafeAssetUrl("https://objects.githubusercontent.com/github-production-release-asset-2e65be/123/bundle.tar.gz")).not.toThrow();
13
+ });
14
+ it("rejects an unauthorised external URL", () => {
15
+ expect(() => assertSafeAssetUrl("https://evil.example.com/malicious.tar.gz")).toThrow("URL de asset não autorizada");
16
+ });
17
+ it("rejects a URL that starts with an allowed prefix but has wrong host", () => {
18
+ expect(() => assertSafeAssetUrl("https://evil.github.com/Shiftleftpt/anything")).toThrow("URL de asset não autorizada");
19
+ });
20
+ });
21
+ // ---------------------------------------------------------------------------
22
+ // assertSafeDestPath
23
+ // ---------------------------------------------------------------------------
24
+ describe("assertSafeDestPath", () => {
25
+ const baseDir = "/tmp/sbd-base";
26
+ it("accepts a path inside baseDir", () => {
27
+ expect(() => assertSafeDestPath(path.join(baseDir, "data", "publish", "file.json"), baseDir)).not.toThrow();
28
+ });
29
+ it("accepts a path equal to baseDir", () => {
30
+ expect(() => assertSafeDestPath(baseDir, baseDir)).not.toThrow();
31
+ });
32
+ it("rejects a path-traversal attempt with ../", () => {
33
+ expect(() => assertSafeDestPath(path.join(baseDir, "..", "..", "etc", "passwd"), baseDir)).toThrow("Path traversal detectado");
34
+ });
35
+ it("rejects an absolute path outside baseDir", () => {
36
+ expect(() => assertSafeDestPath("/usr/local/bin/evil", baseDir)).toThrow("Path traversal detectado");
37
+ });
38
+ });
39
+ // ---------------------------------------------------------------------------
40
+ // fetchReleaseAssetUrl (mocked fetch)
41
+ // ---------------------------------------------------------------------------
42
+ describe("fetchReleaseAssetUrl", () => {
43
+ beforeEach(() => {
44
+ vi.stubGlobal("fetch", vi.fn());
45
+ });
46
+ afterEach(() => {
47
+ vi.unstubAllGlobals();
48
+ });
49
+ it("throws when GitHub API returns 404", async () => {
50
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(null, { status: 404 }));
51
+ await expect(fetchReleaseAssetUrl("latest", 5000)).rejects.toThrow("GitHub API respondeu 404");
52
+ });
53
+ it("throws when release has no assets", async () => {
54
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(JSON.stringify({ assets: [] }), {
55
+ status: 200,
56
+ headers: { "Content-Type": "application/json" },
57
+ }));
58
+ await expect(fetchReleaseAssetUrl("latest", 5000)).rejects.toThrow("Nenhum asset de bundle encontrado");
59
+ });
60
+ it("throws when release has no assets property at all", async () => {
61
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(JSON.stringify({}), {
62
+ status: 200,
63
+ headers: { "Content-Type": "application/json" },
64
+ }));
65
+ await expect(fetchReleaseAssetUrl("latest", 5000)).rejects.toThrow("Nenhum asset de bundle encontrado");
66
+ });
67
+ it("throws when asset URL is not in allowed prefixes", async () => {
68
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(JSON.stringify({
69
+ assets: [
70
+ {
71
+ name: "bundle.tar.gz",
72
+ browser_download_url: "https://evil.example.com/bundle.tar.gz",
73
+ },
74
+ ],
75
+ }), {
76
+ status: 200,
77
+ headers: { "Content-Type": "application/json" },
78
+ }));
79
+ await expect(fetchReleaseAssetUrl("latest", 5000)).rejects.toThrow("URL de asset não autorizada");
80
+ });
81
+ it("returns assetUrl and assetName for a valid release with bundle asset", async () => {
82
+ const downloadUrl = "https://github.com/Shiftleftpt/sbd-toe-knowledge-graph/releases/download/v1.0.0/bundle.tar.gz";
83
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(JSON.stringify({
84
+ assets: [
85
+ {
86
+ name: "bundle.tar.gz",
87
+ browser_download_url: downloadUrl,
88
+ },
89
+ ],
90
+ }), {
91
+ status: 200,
92
+ headers: { "Content-Type": "application/json" },
93
+ }));
94
+ const result = await fetchReleaseAssetUrl("latest", 5000);
95
+ expect(result.assetUrl).toBe(downloadUrl);
96
+ expect(result.assetName).toBe("bundle.tar.gz");
97
+ });
98
+ it("uses tag-specific URL when tag is not 'latest'", async () => {
99
+ const downloadUrl = "https://github.com/Shiftleftpt/sbd-toe-knowledge-graph/releases/download/v2.0.0/bundle.tar.gz";
100
+ vi.mocked(fetch).mockResolvedValueOnce(new Response(JSON.stringify({
101
+ assets: [
102
+ {
103
+ name: "bundle.tar.gz",
104
+ browser_download_url: downloadUrl,
105
+ },
106
+ ],
107
+ }), {
108
+ status: 200,
109
+ headers: { "Content-Type": "application/json" },
110
+ }));
111
+ await fetchReleaseAssetUrl("v2.0.0", 5000);
112
+ const calledUrl = vi.mocked(fetch).mock.calls[0]?.[0];
113
+ expect(calledUrl).toContain("/releases/tags/v2.0.0");
114
+ });
115
+ });
116
+ // ---------------------------------------------------------------------------
117
+ // UPSTREAM_SOURCE config validation
118
+ // ---------------------------------------------------------------------------
119
+ describe("getConfig UPSTREAM_SOURCE validation", () => {
120
+ afterEach(() => {
121
+ vi.unstubAllGlobals();
122
+ // Reset module to clear cached config
123
+ vi.resetModules();
124
+ });
125
+ it("throws when UPSTREAM_SOURCE has an invalid value", async () => {
126
+ process.env["UPSTREAM_SOURCE"] = "INVALID";
127
+ try {
128
+ const { getConfig } = await import("../config.js");
129
+ // Reset cache by re-importing a fresh module (resetModules above)
130
+ expect(() => getConfig()).toThrow("UPSTREAM_SOURCE deve ser 'local' ou 'release'");
131
+ }
132
+ finally {
133
+ delete process.env["UPSTREAM_SOURCE"];
134
+ }
135
+ });
136
+ });
137
+ //# sourceMappingURL=release-checkout.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-checkout.test.js","sourceRoot":"","sources":["../../src/bootstrap/release-checkout.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AppConfig } from "./types.js";
2
+ export declare function getAppRoot(): string;
3
+ export declare function resolveAppPath(filePath: string): string;
4
+ export declare function getConfig(): AppConfig;
package/dist/config.js ADDED
@@ -0,0 +1,81 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ let cachedConfig;
4
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
5
+ const defaultAppRoot = path.resolve(moduleDir, "..");
6
+ function getEnv(name, fallback) {
7
+ const value = process.env[name];
8
+ if (value !== undefined && value.trim().length > 0) {
9
+ return value.trim();
10
+ }
11
+ if (fallback !== undefined) {
12
+ return fallback;
13
+ }
14
+ throw new Error(`Falta definir a variável de ambiente ${name}.`);
15
+ }
16
+ function parseBoolean(value) {
17
+ return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase());
18
+ }
19
+ function parseInteger(name, value, fallback) {
20
+ const parsed = Number.parseInt(value, 10);
21
+ if (Number.isNaN(parsed) || parsed <= 0) {
22
+ throw new Error(`Configuração inválida para ${name}: "${value}".`);
23
+ }
24
+ return parsed || fallback;
25
+ }
26
+ function normalizeBaseUrl(url) {
27
+ return url.endsWith("/") ? url : `${url}/`;
28
+ }
29
+ export function getAppRoot() {
30
+ const override = process.env.SBD_TOE_APP_ROOT;
31
+ if (override !== undefined && override.trim().length > 0) {
32
+ return path.resolve(override.trim());
33
+ }
34
+ return defaultAppRoot;
35
+ }
36
+ export function resolveAppPath(filePath) {
37
+ return path.isAbsolute(filePath) ? filePath : path.resolve(getAppRoot(), filePath);
38
+ }
39
+ export function getConfig() {
40
+ if (cachedConfig) {
41
+ return cachedConfig;
42
+ }
43
+ cachedConfig = {
44
+ backend: {
45
+ docsIndex: getEnv("SEMANTIC_BACKEND_DOCS_INDEX", "SbD-ToE-ASKAI-Docs"),
46
+ entitiesIndex: getEnv("SEMANTIC_BACKEND_ENTITIES_INDEX", "SbD-ToE-ASKAI-Entities"),
47
+ docsHits: parseInteger("DOCS_HITS", getEnv("DOCS_HITS", "8"), 8),
48
+ entitiesHits: parseInteger("ENTITIES_HITS", getEnv("ENTITIES_HITS", "5"), 5),
49
+ maxContextRecords: parseInteger("MAX_CONTEXT_RECORDS", getEnv("MAX_CONTEXT_RECORDS", "8"), 8),
50
+ upstreamRepoDir: getEnv("UPSTREAM_KNOWLEDGE_GRAPH_DIR", "../sbd-toe-knowledge-graph"),
51
+ checkoutFile: getEnv("BACKEND_CHECKOUT_FILE", "./data/upstream/backend-checkout.json"),
52
+ docsSnapshotFile: getEnv("DOCS_SNAPSHOT_FILE", "./data/publish/algolia_docs_records.json"),
53
+ entitiesSnapshotFile: getEnv("ENTITIES_SNAPSHOT_FILE", "./data/publish/algolia_entities_records.json"),
54
+ docsEnrichedSnapshotFile: getEnv("DOCS_ENRICHED_SNAPSHOT_FILE", "./data/publish/algolia_docs_records_enriched.json"),
55
+ entitiesEnrichedSnapshotFile: getEnv("ENTITIES_ENRICHED_SNAPSHOT_FILE", "./data/publish/algolia_entities_records_enriched.json"),
56
+ indexSettingsFile: getEnv("INDEX_SETTINGS_FILE", "./data/publish/algolia_index_settings.json"),
57
+ runManifestFile: getEnv("RUN_MANIFEST_FILE", "./data/reports/run_manifest.json"),
58
+ upstreamSource: (() => {
59
+ const v = getEnv("UPSTREAM_SOURCE", "local");
60
+ if (v !== "local" && v !== "release") {
61
+ throw new Error(`UPSTREAM_SOURCE deve ser 'local' ou 'release', recebido: '${v}'`);
62
+ }
63
+ return v;
64
+ })(),
65
+ upstreamReleaseTag: getEnv("UPSTREAM_RELEASE_TAG", "latest"),
66
+ upstreamReleaseMaxBytes: 100 * 1024 * 1024,
67
+ upstreamReleaseTimeoutMs: 60_000
68
+ },
69
+ prompt: {
70
+ systemPromptFile: getEnv("SYSTEM_PROMPT_FILE", "./prompts/sbd-toe-chat-system.md"),
71
+ defaultLanguage: getEnv("DEFAULT_LANGUAGE", "pt-PT"),
72
+ siteBaseUrl: normalizeBaseUrl(getEnv("SITE_BASE_URL", "https://www.securitybydesign.dev/")),
73
+ manualBaseUrl: normalizeBaseUrl(getEnv("MANUAL_BASE_URL", "https://www.securitybydesign.dev/sbd-toe/sbd-manual/")),
74
+ crossCheckBaseUrl: normalizeBaseUrl(getEnv("CROSS_CHECK_BASE_URL", "https://www.securitybydesign.dev/sbd-toe/cross-check-normativo/")),
75
+ samplingMaxTokens: parseInteger("SAMPLING_MAX_TOKENS", getEnv("SAMPLING_MAX_TOKENS", "1200"), 1200)
76
+ },
77
+ debugMode: parseBoolean(getEnv("DEBUG_MODE", "false"))
78
+ };
79
+ return cachedConfig;
80
+ }
81
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};