@jamesaphoenix/tx-api-server 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/__tests__/api.test.d.ts +7 -0
  2. package/dist/__tests__/api.test.d.ts.map +1 -0
  3. package/dist/__tests__/api.test.js +184 -0
  4. package/dist/__tests__/api.test.js.map +1 -0
  5. package/dist/__tests__/auth.test.d.ts +7 -0
  6. package/dist/__tests__/auth.test.d.ts.map +1 -0
  7. package/dist/__tests__/auth.test.js +174 -0
  8. package/dist/__tests__/auth.test.js.map +1 -0
  9. package/dist/__tests__/body-limit.test.d.ts +7 -0
  10. package/dist/__tests__/body-limit.test.d.ts.map +1 -0
  11. package/dist/__tests__/body-limit.test.js +60 -0
  12. package/dist/__tests__/body-limit.test.js.map +1 -0
  13. package/dist/__tests__/health.test.d.ts.map +1 -0
  14. package/dist/__tests__/health.test.js.map +1 -0
  15. package/dist/__tests__/log-reader.test.d.ts +8 -0
  16. package/dist/__tests__/log-reader.test.d.ts.map +1 -0
  17. package/dist/__tests__/log-reader.test.js +55 -0
  18. package/dist/__tests__/log-reader.test.js.map +1 -0
  19. package/dist/__tests__/rate-limit.test.d.ts.map +1 -0
  20. package/dist/__tests__/rate-limit.test.js.map +1 -0
  21. package/dist/__tests__/server-lib.test.d.ts +10 -0
  22. package/dist/__tests__/server-lib.test.d.ts.map +1 -0
  23. package/dist/__tests__/server-lib.test.js +145 -0
  24. package/dist/__tests__/server-lib.test.js.map +1 -0
  25. package/dist/api.d.ts +1616 -0
  26. package/dist/api.d.ts.map +1 -0
  27. package/dist/api.js +566 -0
  28. package/dist/api.js.map +1 -0
  29. package/dist/index.d.ts +16 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +19 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/middleware/auth.d.ts +31 -0
  34. package/dist/middleware/auth.d.ts.map +1 -0
  35. package/dist/middleware/auth.js +65 -0
  36. package/dist/middleware/auth.js.map +1 -0
  37. package/dist/middleware/body-limit.d.ts +33 -0
  38. package/dist/middleware/body-limit.d.ts.map +1 -0
  39. package/dist/middleware/body-limit.js +50 -0
  40. package/dist/middleware/body-limit.js.map +1 -0
  41. package/dist/middleware/cors.d.ts +15 -0
  42. package/dist/middleware/cors.d.ts.map +1 -0
  43. package/dist/middleware/cors.js +31 -0
  44. package/dist/middleware/cors.js.map +1 -0
  45. package/dist/middleware/error.d.ts +26 -0
  46. package/dist/middleware/error.d.ts.map +1 -0
  47. package/dist/middleware/error.js +84 -0
  48. package/dist/middleware/error.js.map +1 -0
  49. package/dist/middleware/rate-limit.d.ts +59 -0
  50. package/dist/middleware/rate-limit.d.ts.map +1 -0
  51. package/dist/middleware/rate-limit.js +296 -0
  52. package/dist/middleware/rate-limit.js.map +1 -0
  53. package/dist/routes/attempts.d.ts +9 -0
  54. package/dist/routes/attempts.d.ts.map +1 -0
  55. package/dist/routes/attempts.js +26 -0
  56. package/dist/routes/attempts.js.map +1 -0
  57. package/dist/routes/claims.d.ts +9 -0
  58. package/dist/routes/claims.d.ts.map +1 -0
  59. package/dist/routes/claims.js +42 -0
  60. package/dist/routes/claims.js.map +1 -0
  61. package/dist/routes/docs.d.ts +9 -0
  62. package/dist/routes/docs.d.ts.map +1 -0
  63. package/dist/routes/docs.js +80 -0
  64. package/dist/routes/docs.js.map +1 -0
  65. package/dist/routes/health.d.ts +8 -0
  66. package/dist/routes/health.d.ts.map +1 -0
  67. package/dist/routes/health.js +101 -0
  68. package/dist/routes/health.js.map +1 -0
  69. package/dist/routes/invariants.d.ts +9 -0
  70. package/dist/routes/invariants.d.ts.map +1 -0
  71. package/dist/routes/invariants.js +64 -0
  72. package/dist/routes/invariants.js.map +1 -0
  73. package/dist/routes/learnings.d.ts +8 -0
  74. package/dist/routes/learnings.d.ts.map +1 -0
  75. package/dist/routes/learnings.js +93 -0
  76. package/dist/routes/learnings.js.map +1 -0
  77. package/dist/routes/runs.d.ts +8 -0
  78. package/dist/routes/runs.d.ts.map +1 -0
  79. package/dist/routes/runs.js +195 -0
  80. package/dist/routes/runs.js.map +1 -0
  81. package/dist/routes/sync.d.ts +8 -0
  82. package/dist/routes/sync.d.ts.map +1 -0
  83. package/dist/routes/sync.js +67 -0
  84. package/dist/routes/sync.js.map +1 -0
  85. package/dist/routes/tasks.d.ts +9 -0
  86. package/dist/routes/tasks.d.ts.map +1 -0
  87. package/dist/routes/tasks.js +167 -0
  88. package/dist/routes/tasks.js.map +1 -0
  89. package/dist/runtime.d.ts +10 -0
  90. package/dist/runtime.d.ts.map +1 -0
  91. package/dist/runtime.js +10 -0
  92. package/dist/runtime.js.map +1 -0
  93. package/dist/server-lib.d.ts +26 -0
  94. package/dist/server-lib.d.ts.map +1 -0
  95. package/dist/server-lib.js +123 -0
  96. package/dist/server-lib.js.map +1 -0
  97. package/dist/server.d.ts +14 -0
  98. package/dist/server.d.ts.map +1 -0
  99. package/dist/server.js +15 -0
  100. package/dist/server.js.map +1 -0
  101. package/dist/utils/log-reader.d.ts +26 -0
  102. package/dist/utils/log-reader.d.ts.map +1 -0
  103. package/dist/utils/log-reader.js +52 -0
  104. package/dist/utils/log-reader.js.map +1 -0
  105. package/dist/utils/transcript-parser.d.ts +40 -0
  106. package/dist/utils/transcript-parser.d.ts.map +1 -0
  107. package/dist/utils/transcript-parser.js +216 -0
  108. package/dist/utils/transcript-parser.js.map +1 -0
  109. package/package.json +75 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Invariant Route Handlers
3
+ *
4
+ * Implements invariant endpoint handlers using Effect HttpApiBuilder.
5
+ * Manages system invariants and check recording.
6
+ */
7
+ import { DocService } from "@jamesaphoenix/tx-core";
8
+ export declare const InvariantsLive: import("effect/Layer").Layer<import("@effect/platform/HttpApiGroup").ApiGroup<"tx", "invariants">, never, DocService>;
9
+ //# sourceMappingURL=invariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.d.ts","sourceRoot":"","sources":["../../src/routes/invariants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAkCnD,eAAO,MAAM,cAAc,uHAyC1B,CAAA"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Invariant Route Handlers
3
+ *
4
+ * Implements invariant endpoint handlers using Effect HttpApiBuilder.
5
+ * Manages system invariants and check recording.
6
+ */
7
+ import { HttpApiBuilder } from "@effect/platform";
8
+ import { Effect } from "effect";
9
+ import { DocService } from "@jamesaphoenix/tx-core";
10
+ import { TxApi, NotFound, mapCoreError } from "../api.js";
11
+ // -----------------------------------------------------------------------------
12
+ // Serialization Helpers
13
+ // -----------------------------------------------------------------------------
14
+ const serializeInvariant = (inv) => ({
15
+ id: inv.id,
16
+ rule: inv.rule,
17
+ enforcement: inv.enforcement,
18
+ docId: inv.docId,
19
+ subsystem: inv.subsystem,
20
+ testRef: inv.testRef,
21
+ lintRule: inv.lintRule,
22
+ promptRef: inv.promptRef,
23
+ status: inv.status,
24
+ createdAt: inv.createdAt.toISOString(),
25
+ });
26
+ const serializeInvariantCheck = (check) => ({
27
+ id: check.id,
28
+ invariantId: check.invariantId,
29
+ passed: check.passed,
30
+ details: check.details,
31
+ checkedAt: check.checkedAt.toISOString(),
32
+ durationMs: check.durationMs,
33
+ });
34
+ // -----------------------------------------------------------------------------
35
+ // Handler Layer
36
+ // -----------------------------------------------------------------------------
37
+ export const InvariantsLive = HttpApiBuilder.group(TxApi, "invariants", (handlers) => handlers
38
+ .handle("listInvariants", ({ urlParams }) => Effect.gen(function* () {
39
+ const docService = yield* DocService;
40
+ const filter = {};
41
+ if (urlParams.subsystem) {
42
+ filter.subsystem = urlParams.subsystem;
43
+ }
44
+ if (urlParams.enforcement) {
45
+ filter.enforcement = urlParams.enforcement;
46
+ }
47
+ const invariants = yield* docService.listInvariants(filter);
48
+ return { invariants: invariants.map(serializeInvariant) };
49
+ }).pipe(Effect.mapError(mapCoreError)))
50
+ .handle("getInvariant", ({ path }) => Effect.gen(function* () {
51
+ const docService = yield* DocService;
52
+ const invariants = yield* docService.listInvariants();
53
+ const inv = invariants.find(i => i.id === path.id);
54
+ if (!inv) {
55
+ return yield* Effect.fail(new NotFound({ message: `Invariant not found: ${path.id}` }));
56
+ }
57
+ return serializeInvariant(inv);
58
+ }).pipe(Effect.mapError(mapCoreError)))
59
+ .handle("checkInvariant", ({ path, payload }) => Effect.gen(function* () {
60
+ const docService = yield* DocService;
61
+ const check = yield* docService.recordInvariantCheck(path.id, payload.passed, payload.details, payload.durationMs);
62
+ return serializeInvariantCheck(check);
63
+ }).pipe(Effect.mapError(mapCoreError))));
64
+ //# sourceMappingURL=invariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invariants.js","sourceRoot":"","sources":["../../src/routes/invariants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Learning Route Handlers
3
+ *
4
+ * Implements learning and file learning endpoint handlers.
5
+ */
6
+ import { LearningService, FileLearningService } from "@jamesaphoenix/tx-core";
7
+ export declare const LearningsLive: import("effect/Layer").Layer<import("@effect/platform/HttpApiGroup").ApiGroup<"tx", "learnings">, never, LearningService | FileLearningService>;
8
+ //# sourceMappingURL=learnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../../src/routes/learnings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAO7E,eAAO,MAAM,aAAa,iJA0GzB,CAAA"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Learning Route Handlers
3
+ *
4
+ * Implements learning and file learning endpoint handlers.
5
+ */
6
+ import { HttpApiBuilder } from "@effect/platform";
7
+ import { Effect } from "effect";
8
+ import { serializeLearning, serializeLearningWithScore, serializeFileLearning } from "@jamesaphoenix/tx-types";
9
+ import { LearningService, FileLearningService } from "@jamesaphoenix/tx-core";
10
+ import { TxApi, mapCoreError } from "../api.js";
11
+ // -----------------------------------------------------------------------------
12
+ // Handler Layer
13
+ // -----------------------------------------------------------------------------
14
+ export const LearningsLive = HttpApiBuilder.group(TxApi, "learnings", (handlers) => handlers
15
+ .handle("searchLearnings", ({ urlParams }) => Effect.gen(function* () {
16
+ const learningService = yield* LearningService;
17
+ const limit = urlParams.limit ?? 10;
18
+ let learnings;
19
+ if (!urlParams.query) {
20
+ learnings = yield* learningService.getRecent(limit);
21
+ }
22
+ else {
23
+ learnings = yield* learningService.search({
24
+ query: urlParams.query,
25
+ limit,
26
+ minScore: urlParams.minScore ?? undefined,
27
+ category: urlParams.category ?? undefined,
28
+ });
29
+ }
30
+ // Ensure all results have score fields
31
+ const isWithScore = (l) => "relevanceScore" in l;
32
+ return {
33
+ learnings: learnings.map(l => isWithScore(l) ? serializeLearningWithScore(l) : serializeLearningWithScore({
34
+ ...l,
35
+ relevanceScore: 1,
36
+ bm25Score: 0,
37
+ vectorScore: 0,
38
+ recencyScore: 0,
39
+ rrfScore: 0,
40
+ bm25Rank: 0,
41
+ vectorRank: 0,
42
+ })),
43
+ };
44
+ }).pipe(Effect.mapError(mapCoreError)))
45
+ .handle("getLearning", ({ path }) => Effect.gen(function* () {
46
+ const learningService = yield* LearningService;
47
+ const learning = yield* learningService.get(path.id);
48
+ return serializeLearning(learning);
49
+ }).pipe(Effect.mapError(mapCoreError)))
50
+ .handle("createLearning", ({ payload }) => Effect.gen(function* () {
51
+ const learningService = yield* LearningService;
52
+ const learning = yield* learningService.create({
53
+ content: payload.content,
54
+ sourceType: payload.sourceType ?? "manual",
55
+ sourceRef: payload.sourceRef ?? undefined,
56
+ category: payload.category ?? undefined,
57
+ keywords: payload.keywords ?? undefined,
58
+ });
59
+ return serializeLearning(learning);
60
+ }).pipe(Effect.mapError(mapCoreError)))
61
+ .handle("updateHelpfulness", ({ path, payload }) => Effect.gen(function* () {
62
+ const learningService = yield* LearningService;
63
+ yield* learningService.updateOutcome(path.id, payload.score);
64
+ return { success: true, id: path.id, score: payload.score };
65
+ }).pipe(Effect.mapError(mapCoreError)))
66
+ .handle("getContext", ({ path }) => Effect.gen(function* () {
67
+ const learningService = yield* LearningService;
68
+ const result = yield* learningService.getContextForTask(path.taskId);
69
+ return {
70
+ taskId: result.taskId,
71
+ taskTitle: result.taskTitle,
72
+ learnings: result.learnings.map(serializeLearningWithScore),
73
+ searchQuery: result.searchQuery,
74
+ searchDuration: result.searchDuration,
75
+ };
76
+ }).pipe(Effect.mapError(mapCoreError)))
77
+ .handle("listFileLearnings", ({ urlParams }) => Effect.gen(function* () {
78
+ const fileLearningService = yield* FileLearningService;
79
+ const learnings = urlParams.path
80
+ ? yield* fileLearningService.recall(urlParams.path)
81
+ : yield* fileLearningService.getAll();
82
+ return { learnings: learnings.map(serializeFileLearning) };
83
+ }).pipe(Effect.mapError(mapCoreError)))
84
+ .handle("createFileLearning", ({ payload }) => Effect.gen(function* () {
85
+ const fileLearningService = yield* FileLearningService;
86
+ const learning = yield* fileLearningService.create({
87
+ filePattern: payload.filePattern,
88
+ note: payload.note,
89
+ taskId: payload.taskId ?? undefined,
90
+ });
91
+ return serializeFileLearning(learning);
92
+ }).pipe(Effect.mapError(mapCoreError))));
93
+ //# sourceMappingURL=learnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/routes/learnings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Run Route Handlers
3
+ *
4
+ * Implements run tracking endpoint handlers.
5
+ */
6
+ import { RunRepository } from "@jamesaphoenix/tx-core";
7
+ export declare const RunsLive: import("effect/Layer").Layer<import("@effect/platform/HttpApiGroup").ApiGroup<"tx", "runs">, never, RunRepository>;
8
+ //# sourceMappingURL=runs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/routes/runs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AA+BtD,eAAO,MAAM,QAAQ,oHA0NpB,CAAA"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Run Route Handlers
3
+ *
4
+ * Implements run tracking endpoint handlers.
5
+ */
6
+ import { HttpApiBuilder } from "@effect/platform";
7
+ import { Effect } from "effect";
8
+ import { serializeRun } from "@jamesaphoenix/tx-types";
9
+ import { RunRepository } from "@jamesaphoenix/tx-core";
10
+ import { TxApi, NotFound, BadRequest, mapCoreError } from "../api.js";
11
+ import { parseTranscript, findMatchingTranscript, isAllowedTranscriptPath } from "../utils/transcript-parser.js";
12
+ import { readLogFile, isAllowedRunPath } from "../utils/log-reader.js";
13
+ const parseRunCursor = (cursor) => {
14
+ const colonIndex = cursor.lastIndexOf(":");
15
+ if (colonIndex === -1)
16
+ return null;
17
+ return {
18
+ startedAt: cursor.slice(0, colonIndex),
19
+ id: cursor.slice(colonIndex + 1),
20
+ };
21
+ };
22
+ const buildRunCursor = (run) => {
23
+ return `${run.startedAt.toISOString()}:${run.id}`;
24
+ };
25
+ // -----------------------------------------------------------------------------
26
+ // Handler Layer
27
+ // -----------------------------------------------------------------------------
28
+ export const RunsLive = HttpApiBuilder.group(TxApi, "runs", (handlers) => handlers
29
+ .handle("listRuns", ({ urlParams }) => Effect.gen(function* () {
30
+ const runRepo = yield* RunRepository;
31
+ const limit = urlParams.limit ?? 20;
32
+ // Get runs based on filters
33
+ let allRuns;
34
+ if (urlParams.taskId) {
35
+ allRuns = yield* runRepo.findByTaskId(urlParams.taskId);
36
+ }
37
+ else if (urlParams.status && urlParams.status.split(",").length === 1) {
38
+ allRuns = yield* runRepo.findByStatus(urlParams.status);
39
+ }
40
+ else {
41
+ // TODO: Push agent/multi-status filtering down to the repository layer
42
+ // to avoid loading excessive runs into memory for in-JS filtering.
43
+ // Using a high limit to reduce silent data loss from in-memory filtering.
44
+ allRuns = yield* runRepo.findRecent(10_000);
45
+ }
46
+ // Apply additional filters in memory
47
+ let filtered = [...allRuns];
48
+ if (urlParams.agent) {
49
+ filtered = filtered.filter(r => r.agent === urlParams.agent);
50
+ }
51
+ if (urlParams.status && urlParams.status.split(",").length > 1) {
52
+ const statusFilter = urlParams.status.split(",").filter(Boolean);
53
+ filtered = filtered.filter(r => statusFilter.includes(r.status));
54
+ }
55
+ // Sort by startedAt DESC, id ASC
56
+ filtered.sort((a, b) => {
57
+ const aTime = a.startedAt.getTime();
58
+ const bTime = b.startedAt.getTime();
59
+ if (aTime !== bTime)
60
+ return bTime - aTime;
61
+ return a.id.localeCompare(b.id);
62
+ });
63
+ // Apply cursor pagination
64
+ let startIndex = 0;
65
+ if (urlParams.cursor) {
66
+ const parsed = parseRunCursor(urlParams.cursor);
67
+ if (parsed) {
68
+ const cursorTime = new Date(parsed.startedAt).getTime();
69
+ startIndex = filtered.findIndex(r => r.startedAt.getTime() < cursorTime ||
70
+ (r.startedAt.getTime() === cursorTime && r.id > parsed.id));
71
+ if (startIndex === -1)
72
+ startIndex = filtered.length;
73
+ }
74
+ }
75
+ const total = filtered.length;
76
+ const paginated = filtered.slice(startIndex, startIndex + limit + 1);
77
+ const hasMore = paginated.length > limit;
78
+ const resultRuns = hasMore ? paginated.slice(0, limit) : paginated;
79
+ return {
80
+ runs: resultRuns.map(serializeRun),
81
+ nextCursor: hasMore && resultRuns.length > 0
82
+ ? buildRunCursor(resultRuns[resultRuns.length - 1])
83
+ : null,
84
+ hasMore,
85
+ total,
86
+ };
87
+ }).pipe(Effect.mapError(mapCoreError)))
88
+ .handle("getRun", ({ path }) => Effect.gen(function* () {
89
+ const runRepo = yield* RunRepository;
90
+ const found = yield* runRepo.findById(path.id);
91
+ if (!found) {
92
+ return yield* Effect.fail(new NotFound({ message: `Run not found: ${path.id}` }));
93
+ }
94
+ // Parse transcript if available
95
+ let messages = [];
96
+ let transcriptPath = found.transcriptPath;
97
+ // If no explicit transcript path, try to find one by timestamp correlation
98
+ if (!transcriptPath) {
99
+ // Derive project root from DB path (e.g. /path/to/project/.tx/tasks.db -> /path/to/project)
100
+ // Falls back to process.cwd() if TX_DB_PATH is not absolute
101
+ const dbPath = process.env.TX_DB_PATH ?? "";
102
+ const projectRoot = dbPath.includes("/.tx/")
103
+ ? dbPath.slice(0, dbPath.indexOf("/.tx/"))
104
+ : process.cwd();
105
+ const discovered = yield* Effect.tryPromise({
106
+ try: () => findMatchingTranscript(projectRoot, found.startedAt, found.endedAt),
107
+ catch: () => null,
108
+ });
109
+ transcriptPath = discovered;
110
+ }
111
+ if (transcriptPath) {
112
+ const parsed = yield* parseTranscript(transcriptPath).pipe(Effect.catchAll(() => Effect.succeed([])));
113
+ messages = parsed;
114
+ }
115
+ return {
116
+ run: serializeRun(found),
117
+ messages: messages,
118
+ };
119
+ }).pipe(Effect.mapError(mapCoreError)))
120
+ .handle("createRun", ({ payload }) => Effect.gen(function* () {
121
+ // Security: validate transcriptPath before storing
122
+ if (payload.transcriptPath && !isAllowedTranscriptPath(payload.transcriptPath)) {
123
+ return yield* Effect.fail(new BadRequest({ message: "Invalid transcriptPath: must be under ~/.claude/ or .tx/" }));
124
+ }
125
+ // Security: validate contextInjected path is under .tx/runs/ (prefix match, not substring)
126
+ if (payload.contextInjected) {
127
+ if (!isAllowedRunPath(payload.contextInjected)) {
128
+ return yield* Effect.fail(new BadRequest({ message: "Invalid contextInjected: must be under .tx/runs/" }));
129
+ }
130
+ }
131
+ const runRepo = yield* RunRepository;
132
+ const run = yield* runRepo.create({
133
+ taskId: payload.taskId,
134
+ agent: payload.agent,
135
+ pid: payload.pid,
136
+ transcriptPath: payload.transcriptPath,
137
+ contextInjected: payload.contextInjected,
138
+ metadata: payload.metadata,
139
+ });
140
+ return serializeRun(run);
141
+ }).pipe(Effect.mapError(mapCoreError)))
142
+ .handle("updateRun", ({ path, payload }) => Effect.gen(function* () {
143
+ // Security: validate transcriptPath before storing
144
+ if (payload.transcriptPath && !isAllowedTranscriptPath(payload.transcriptPath)) {
145
+ return yield* Effect.fail(new BadRequest({ message: "Invalid transcriptPath: must be under ~/.claude/ or .tx/" }));
146
+ }
147
+ const runRepo = yield* RunRepository;
148
+ yield* runRepo.update(path.id, {
149
+ status: payload.status,
150
+ endedAt: payload.endedAt ? new Date(payload.endedAt) : undefined,
151
+ exitCode: payload.exitCode,
152
+ summary: payload.summary,
153
+ errorMessage: payload.errorMessage,
154
+ transcriptPath: payload.transcriptPath,
155
+ });
156
+ const updated = yield* runRepo.findById(path.id);
157
+ if (!updated) {
158
+ return yield* Effect.fail(new NotFound({ message: `Run not found: ${path.id}` }));
159
+ }
160
+ return serializeRun(updated);
161
+ }).pipe(Effect.mapError(mapCoreError)))
162
+ .handle("getRunStdout", ({ path, urlParams }) => Effect.gen(function* () {
163
+ const runRepo = yield* RunRepository;
164
+ const found = yield* runRepo.findById(path.id);
165
+ if (!found) {
166
+ return yield* Effect.fail(new NotFound({ message: `Run not found: ${path.id}` }));
167
+ }
168
+ if (!found.stdoutPath) {
169
+ return { content: "", truncated: false };
170
+ }
171
+ return yield* readLogFile(found.stdoutPath, urlParams.tail ?? 0).pipe(Effect.catchAll(() => Effect.succeed({ content: "", truncated: false })));
172
+ }).pipe(Effect.mapError(mapCoreError)))
173
+ .handle("getRunStderr", ({ path, urlParams }) => Effect.gen(function* () {
174
+ const runRepo = yield* RunRepository;
175
+ const found = yield* runRepo.findById(path.id);
176
+ if (!found) {
177
+ return yield* Effect.fail(new NotFound({ message: `Run not found: ${path.id}` }));
178
+ }
179
+ if (!found.stderrPath) {
180
+ return { content: "", truncated: false };
181
+ }
182
+ return yield* readLogFile(found.stderrPath, urlParams.tail ?? 0).pipe(Effect.catchAll(() => Effect.succeed({ content: "", truncated: false })));
183
+ }).pipe(Effect.mapError(mapCoreError)))
184
+ .handle("getRunContext", ({ path }) => Effect.gen(function* () {
185
+ const runRepo = yield* RunRepository;
186
+ const found = yield* runRepo.findById(path.id);
187
+ if (!found) {
188
+ return yield* Effect.fail(new NotFound({ message: `Run not found: ${path.id}` }));
189
+ }
190
+ if (!found.contextInjected) {
191
+ return { content: "", truncated: false };
192
+ }
193
+ return yield* readLogFile(found.contextInjected).pipe(Effect.catchAll(() => Effect.succeed({ content: "", truncated: false })));
194
+ }).pipe(Effect.mapError(mapCoreError))));
195
+ //# sourceMappingURL=runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/routes/runs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Sync Route Handlers
3
+ *
4
+ * Implements JSONL-based git-tracked sync endpoint handlers.
5
+ */
6
+ import { SyncService } from "@jamesaphoenix/tx-core";
7
+ export declare const SyncLive: import("effect/Layer").Layer<import("@effect/platform/HttpApiGroup").ApiGroup<"tx", "sync">, never, SyncService>;
8
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAiCpD,eAAO,MAAM,QAAQ,kHA2CpB,CAAA"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Sync Route Handlers
3
+ *
4
+ * Implements JSONL-based git-tracked sync endpoint handlers.
5
+ */
6
+ import { HttpApiBuilder } from "@effect/platform";
7
+ import { Effect } from "effect";
8
+ import { resolve, sep } from "node:path";
9
+ import { SyncService } from "@jamesaphoenix/tx-core";
10
+ import { TxApi, BadRequest, mapCoreError } from "../api.js";
11
+ // -----------------------------------------------------------------------------
12
+ // Path Validation
13
+ // -----------------------------------------------------------------------------
14
+ /**
15
+ * Validate that a user-provided sync file path does not escape the project
16
+ * directory via path traversal (e.g. "../../etc/passwd" or absolute paths
17
+ * outside the project root).
18
+ *
19
+ * Returns Effect that fails with BadRequest on invalid path.
20
+ */
21
+ const validateSyncPath = (userPath) => {
22
+ if (userPath === undefined)
23
+ return Effect.succeed(undefined);
24
+ const projectRoot = process.cwd();
25
+ const resolved = resolve(projectRoot, userPath);
26
+ if (!resolved.startsWith(projectRoot + sep)) {
27
+ return Effect.fail(new BadRequest({
28
+ message: "Path traversal rejected: sync file path must be within the project directory",
29
+ }));
30
+ }
31
+ return Effect.succeed(userPath);
32
+ };
33
+ // -----------------------------------------------------------------------------
34
+ // Handler Layer
35
+ // -----------------------------------------------------------------------------
36
+ export const SyncLive = HttpApiBuilder.group(TxApi, "sync", (handlers) => handlers
37
+ .handle("syncExport", ({ payload }) => Effect.gen(function* () {
38
+ const safePath = yield* validateSyncPath(payload.path);
39
+ const syncService = yield* SyncService;
40
+ const result = yield* syncService.export(safePath ?? undefined);
41
+ return { opCount: result.opCount, path: result.path };
42
+ }).pipe(Effect.mapError(mapCoreError)))
43
+ .handle("syncImport", ({ payload }) => Effect.gen(function* () {
44
+ const safePath = yield* validateSyncPath(payload.path);
45
+ const syncService = yield* SyncService;
46
+ const result = yield* syncService.import(safePath ?? undefined);
47
+ return { imported: result.imported, skipped: result.skipped, conflicts: result.conflicts };
48
+ }).pipe(Effect.mapError(mapCoreError)))
49
+ .handle("syncStatus", () => Effect.gen(function* () {
50
+ const syncService = yield* SyncService;
51
+ const status = yield* syncService.status();
52
+ return {
53
+ dbTaskCount: status.dbTaskCount,
54
+ jsonlOpCount: status.jsonlOpCount,
55
+ lastExport: status.lastExport?.toISOString() ?? null,
56
+ lastImport: status.lastImport?.toISOString() ?? null,
57
+ isDirty: status.isDirty,
58
+ autoSyncEnabled: status.autoSyncEnabled,
59
+ };
60
+ }).pipe(Effect.mapError(mapCoreError)))
61
+ .handle("syncCompact", ({ payload }) => Effect.gen(function* () {
62
+ const safePath = yield* validateSyncPath(payload.path);
63
+ const syncService = yield* SyncService;
64
+ const result = yield* syncService.compact(safePath ?? undefined);
65
+ return { before: result.before, after: result.after };
66
+ }).pipe(Effect.mapError(mapCoreError))));
67
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Task Route Handlers
3
+ *
4
+ * Implements task endpoint handlers using Effect HttpApiBuilder.
5
+ * All responses return TaskWithDeps per Doctrine Rule 1.
6
+ */
7
+ import { TaskService, ReadyService, DependencyService, HierarchyService } from "@jamesaphoenix/tx-core";
8
+ export declare const TasksLive: import("effect/Layer").Layer<import("@effect/platform/HttpApiGroup").ApiGroup<"tx", "tasks">, never, TaskService | ReadyService | DependencyService | HierarchyService>;
9
+ //# sourceMappingURL=tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/routes/tasks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AA6BvG,eAAO,MAAM,SAAS,yKAwLrB,CAAA"}