@x12i/memorix-client-api 0.18.0 → 0.19.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/HANDOVER.md +13 -2
- package/dist/agent-directory.d.ts +25 -0
- package/dist/agent-directory.d.ts.map +1 -0
- package/dist/agent-directory.js +75 -0
- package/dist/agent-directory.js.map +1 -0
- package/dist/app.d.ts +31 -6
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +220 -33
- package/dist/app.js.map +1 -1
- package/dist/authix.d.ts +28 -2
- package/dist/authix.d.ts.map +1 -1
- package/dist/authix.js +55 -4
- package/dist/authix.js.map +1 -1
- package/dist/catalog.d.ts +33 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +83 -4
- package/dist/catalog.js.map +1 -1
- package/dist/cli.js +11 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +16 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +16 -2
- package/dist/errors.js.map +1 -1
- package/dist/fetch.d.ts.map +1 -1
- package/dist/fetch.js +27 -3
- package/dist/fetch.js.map +1 -1
- package/dist/peers.d.ts +2 -2
- package/dist/peers.d.ts.map +1 -1
- package/dist/peers.js +4 -4
- package/dist/peers.js.map +1 -1
- package/dist/refs.d.ts +7 -1
- package/dist/refs.d.ts.map +1 -1
- package/dist/refs.js +36 -26
- package/dist/refs.js.map +1 -1
- package/dist/scope.d.ts +25 -2
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +71 -4
- package/dist/scope.js.map +1 -1
- package/dist/scoper-embedded.d.ts +29 -0
- package/dist/scoper-embedded.d.ts.map +1 -0
- package/dist/scoper-embedded.js +239 -0
- package/dist/scoper-embedded.js.map +1 -0
- package/dist/scoper.d.ts +19 -27
- package/dist/scoper.d.ts.map +1 -1
- package/dist/scoper.js +51 -254
- package/dist/scoper.js.map +1 -1
- package/dist/upstream.d.ts +6 -1
- package/dist/upstream.d.ts.map +1 -1
- package/dist/upstream.js +22 -4
- package/dist/upstream.js.map +1 -1
- package/dist/v1/census.d.ts +59 -0
- package/dist/v1/census.d.ts.map +1 -0
- package/dist/v1/census.js +146 -0
- package/dist/v1/census.js.map +1 -0
- package/dist/v1/content.d.ts +48 -0
- package/dist/v1/content.d.ts.map +1 -0
- package/dist/v1/content.js +292 -0
- package/dist/v1/content.js.map +1 -0
- package/dist/v1/context.d.ts +50 -0
- package/dist/v1/context.d.ts.map +1 -0
- package/dist/v1/context.js +4 -0
- package/dist/v1/context.js.map +1 -0
- package/dist/v1/discovery.d.ts +24 -0
- package/dist/v1/discovery.d.ts.map +1 -0
- package/dist/v1/discovery.js +163 -0
- package/dist/v1/discovery.js.map +1 -0
- package/dist/v1/gaps.d.ts +18 -0
- package/dist/v1/gaps.d.ts.map +1 -0
- package/dist/v1/gaps.js +2 -0
- package/dist/v1/gaps.js.map +1 -0
- package/dist/v1/http.d.ts +18 -0
- package/dist/v1/http.d.ts.map +1 -0
- package/dist/v1/http.js +105 -0
- package/dist/v1/http.js.map +1 -0
- package/dist/v1/mapping.d.ts +155 -0
- package/dist/v1/mapping.d.ts.map +1 -0
- package/dist/v1/mapping.js +380 -0
- package/dist/v1/mapping.js.map +1 -0
- package/dist/v1/planning-store.d.ts +74 -0
- package/dist/v1/planning-store.d.ts.map +1 -0
- package/dist/v1/planning-store.js +192 -0
- package/dist/v1/planning-store.js.map +1 -0
- package/dist/v1/planning.d.ts +5 -0
- package/dist/v1/planning.d.ts.map +1 -0
- package/dist/v1/planning.js +297 -0
- package/dist/v1/planning.js.map +1 -0
- package/dist/v1/records.d.ts +18 -0
- package/dist/v1/records.d.ts.map +1 -0
- package/dist/v1/records.js +42 -0
- package/dist/v1/records.js.map +1 -0
- package/dist/v1/relationships.d.ts +72 -0
- package/dist/v1/relationships.d.ts.map +1 -0
- package/dist/v1/relationships.js +436 -0
- package/dist/v1/relationships.js.map +1 -0
- package/dist/v1/routes.d.ts +5 -0
- package/dist/v1/routes.d.ts.map +1 -0
- package/dist/v1/routes.js +16 -0
- package/dist/v1/routes.js.map +1 -0
- package/dist/v1/sources.d.ts +62 -0
- package/dist/v1/sources.d.ts.map +1 -0
- package/dist/v1/sources.js +218 -0
- package/dist/v1/sources.js.map +1 -0
- package/openapi/openapi.json +3587 -480
- package/package.json +74 -74
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { ApiError } from "../errors.js";
|
|
3
|
+
export function newPlanningId() {
|
|
4
|
+
return `pln_${Date.now().toString(36).padStart(9, "0")}${randomBytes(5).toString("hex")}`;
|
|
5
|
+
}
|
|
6
|
+
export function planningDatabaseName(orgId) {
|
|
7
|
+
const id = orgId.trim().toLowerCase();
|
|
8
|
+
if (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(id)) {
|
|
9
|
+
throw new ApiError(400, "SCOPE_INVALID", "org id cannot name a planning database");
|
|
10
|
+
}
|
|
11
|
+
return `${id}-memorix-assistants`;
|
|
12
|
+
}
|
|
13
|
+
function matches(item, filter) {
|
|
14
|
+
if (item.archived !== filter.archived)
|
|
15
|
+
return false;
|
|
16
|
+
if (filter.stage && item.stage !== filter.stage)
|
|
17
|
+
return false;
|
|
18
|
+
if (filter.priority && item.priority !== filter.priority)
|
|
19
|
+
return false;
|
|
20
|
+
if (filter.assigneeId !== undefined && item.assigneeId !== filter.assigneeId)
|
|
21
|
+
return false;
|
|
22
|
+
const target = item.target;
|
|
23
|
+
if (filter.objectType && target.objectType !== filter.objectType && target.fromObjectType !== filter.objectType && target.toObjectType !== filter.objectType) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (filter.contentType && target.contentType !== filter.contentType)
|
|
27
|
+
return false;
|
|
28
|
+
if (filter.definitionId && target.definitionId !== filter.definitionId)
|
|
29
|
+
return false;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
/** Items in process memory. Tests and single-process demos. */
|
|
33
|
+
export function createMemoryPlanningStore() {
|
|
34
|
+
const orgs = new Map();
|
|
35
|
+
const itemsOf = (orgId) => {
|
|
36
|
+
let items = orgs.get(orgId);
|
|
37
|
+
if (!items) {
|
|
38
|
+
items = new Map();
|
|
39
|
+
orgs.set(orgId, items);
|
|
40
|
+
}
|
|
41
|
+
return items;
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
async list(orgId, filter, page) {
|
|
45
|
+
const sorted = [...itemsOf(orgId).values()]
|
|
46
|
+
.filter((item) => matches(item, filter))
|
|
47
|
+
.sort((a, b) => b.id.localeCompare(a.id))
|
|
48
|
+
.filter((item) => !page.after || item.id < page.after);
|
|
49
|
+
const items = sorted.slice(0, page.limit);
|
|
50
|
+
return { items: structuredClone(items), ...(sorted.length > page.limit ? { next: items.at(-1).id } : {}) };
|
|
51
|
+
},
|
|
52
|
+
async get(orgId, id) {
|
|
53
|
+
const item = itemsOf(orgId).get(id);
|
|
54
|
+
return item ? structuredClone(item) : null;
|
|
55
|
+
},
|
|
56
|
+
async insert(orgId, item) {
|
|
57
|
+
const items = itemsOf(orgId);
|
|
58
|
+
if (item.clientKey) {
|
|
59
|
+
const existing = [...items.values()].find((stored) => stored.clientKey === item.clientKey);
|
|
60
|
+
if (existing)
|
|
61
|
+
return { item: structuredClone(existing), created: false };
|
|
62
|
+
}
|
|
63
|
+
items.set(item.id, structuredClone(item));
|
|
64
|
+
return { item: structuredClone(item), created: true };
|
|
65
|
+
},
|
|
66
|
+
async update(orgId, id, expectedRevision, changes, actor) {
|
|
67
|
+
const items = itemsOf(orgId);
|
|
68
|
+
const current = items.get(id);
|
|
69
|
+
if (!current || (expectedRevision !== null && current.revision !== expectedRevision)) {
|
|
70
|
+
return { ok: false, current: current ? structuredClone(current) : null };
|
|
71
|
+
}
|
|
72
|
+
const next = {
|
|
73
|
+
...current,
|
|
74
|
+
...changes,
|
|
75
|
+
revision: current.revision + 1,
|
|
76
|
+
updatedBy: actor,
|
|
77
|
+
updatedAt: new Date().toISOString(),
|
|
78
|
+
};
|
|
79
|
+
items.set(id, next);
|
|
80
|
+
return { ok: true, item: structuredClone(next) };
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function fromDocument(doc) {
|
|
85
|
+
if (!doc)
|
|
86
|
+
return null;
|
|
87
|
+
const { _id: _ignored, ...rest } = doc;
|
|
88
|
+
return rest;
|
|
89
|
+
}
|
|
90
|
+
function mongoFilter(filter) {
|
|
91
|
+
const query = { archived: filter.archived };
|
|
92
|
+
if (filter.stage)
|
|
93
|
+
query.stage = filter.stage;
|
|
94
|
+
if (filter.priority)
|
|
95
|
+
query.priority = filter.priority;
|
|
96
|
+
if (filter.assigneeId !== undefined)
|
|
97
|
+
query.assigneeId = filter.assigneeId;
|
|
98
|
+
if (filter.objectType) {
|
|
99
|
+
query.$or = [
|
|
100
|
+
{ "target.objectType": filter.objectType },
|
|
101
|
+
{ "target.fromObjectType": filter.objectType },
|
|
102
|
+
{ "target.toObjectType": filter.objectType },
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
if (filter.contentType)
|
|
106
|
+
query["target.contentType"] = filter.contentType;
|
|
107
|
+
if (filter.definitionId)
|
|
108
|
+
query["target.definitionId"] = filter.definitionId;
|
|
109
|
+
return query;
|
|
110
|
+
}
|
|
111
|
+
/** Items in collection `planning_items` of `{orgId}-memorix-assistants`. */
|
|
112
|
+
export function createMongoPlanningStore(uri) {
|
|
113
|
+
let client = null;
|
|
114
|
+
const ready = new Map();
|
|
115
|
+
function collection(orgId) {
|
|
116
|
+
const name = planningDatabaseName(orgId);
|
|
117
|
+
let hit = ready.get(name);
|
|
118
|
+
if (!hit) {
|
|
119
|
+
hit = (async () => {
|
|
120
|
+
if (!client) {
|
|
121
|
+
const specifier = "mongodb";
|
|
122
|
+
client = import(specifier).then((mod) => new mod.MongoClient(uri).connect());
|
|
123
|
+
client.catch(() => {
|
|
124
|
+
client = null;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const coll = (await client).db(name).collection("planning_items");
|
|
128
|
+
await coll.createIndex({ id: 1 }, { unique: true, name: "planning_id" });
|
|
129
|
+
await coll.createIndex({ clientKey: 1 }, { unique: true, name: "planning_client_key", partialFilterExpression: { clientKey: { $type: "string" } } });
|
|
130
|
+
return coll;
|
|
131
|
+
})();
|
|
132
|
+
hit.catch(() => ready.delete(name));
|
|
133
|
+
ready.set(name, hit);
|
|
134
|
+
}
|
|
135
|
+
return hit;
|
|
136
|
+
}
|
|
137
|
+
async function guarded(work) {
|
|
138
|
+
try {
|
|
139
|
+
return await work();
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
if (err instanceof ApiError)
|
|
143
|
+
throw err;
|
|
144
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
145
|
+
throw new ApiError(503, "PERSISTENCE", `planning store is unavailable: ${message}`, { retryable: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
list: (orgId, filter, page) => guarded(async () => {
|
|
150
|
+
const coll = await collection(orgId);
|
|
151
|
+
const query = mongoFilter(filter);
|
|
152
|
+
if (page.after)
|
|
153
|
+
query.id = { $lt: page.after };
|
|
154
|
+
const docs = await coll.find(query, { projection: { _id: 0 } }).sort({ id: -1 }).limit(page.limit + 1).toArray();
|
|
155
|
+
const items = docs.slice(0, page.limit).map((doc) => fromDocument(doc));
|
|
156
|
+
return { items, ...(docs.length > page.limit ? { next: items.at(-1).id } : {}) };
|
|
157
|
+
}),
|
|
158
|
+
get: (orgId, id) => guarded(async () => fromDocument(await (await collection(orgId)).findOne({ id }, { projection: { _id: 0 } }))),
|
|
159
|
+
insert: (orgId, item) => guarded(async () => {
|
|
160
|
+
const coll = await collection(orgId);
|
|
161
|
+
if (item.clientKey) {
|
|
162
|
+
const existing = fromDocument(await coll.findOne({ clientKey: item.clientKey }, { projection: { _id: 0 } }));
|
|
163
|
+
if (existing)
|
|
164
|
+
return { item: existing, created: false };
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
await coll.insertOne({ ...item });
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
if (err.code === 11000 && item.clientKey) {
|
|
171
|
+
const existing = fromDocument(await coll.findOne({ clientKey: item.clientKey }, { projection: { _id: 0 } }));
|
|
172
|
+
if (existing)
|
|
173
|
+
return { item: existing, created: false };
|
|
174
|
+
}
|
|
175
|
+
throw err;
|
|
176
|
+
}
|
|
177
|
+
return { item, created: true };
|
|
178
|
+
}),
|
|
179
|
+
update: (orgId, id, expectedRevision, changes, actor) => guarded(async () => {
|
|
180
|
+
const coll = await collection(orgId);
|
|
181
|
+
const filter = { id };
|
|
182
|
+
if (expectedRevision !== null)
|
|
183
|
+
filter.revision = expectedRevision;
|
|
184
|
+
const result = await coll.findOneAndUpdate(filter, { $set: { ...changes, updatedBy: actor, updatedAt: new Date().toISOString() }, $inc: { revision: 1 } }, { returnDocument: "after", projection: { _id: 0 }, includeResultMetadata: false });
|
|
185
|
+
const updated = fromDocument(result);
|
|
186
|
+
if (updated)
|
|
187
|
+
return { ok: true, item: updated };
|
|
188
|
+
return { ok: false, current: fromDocument(await coll.findOne({ id }, { projection: { _id: 0 } })) };
|
|
189
|
+
}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=planning-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planning-store.js","sourceRoot":"","sources":["../../src/v1/planning-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { V1Deps } from "./context.js";
|
|
3
|
+
export declare const PLANNING_WRITE_FEATURE = "memorix-planning-write";
|
|
4
|
+
export declare function registerPlanningRoutes(app: FastifyInstance, deps: V1Deps): void;
|
|
5
|
+
//# sourceMappingURL=planning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../src/v1/planning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAK7E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAa3C,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAqE/D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA6O/E"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { tokenHasFeature } from "../authix.js";
|
|
2
|
+
import { ApiError, capabilityUnavailable } from "../errors.js";
|
|
3
|
+
import { scopeBody } from "../scope.js";
|
|
4
|
+
import { limitOf, queryOf, text } from "./http.js";
|
|
5
|
+
import { newPlanningId, } from "./planning-store.js";
|
|
6
|
+
import { loadDefinitions } from "./relationships.js";
|
|
7
|
+
export const PLANNING_WRITE_FEATURE = "memorix-planning-write";
|
|
8
|
+
const CATEGORIES = ["data-gap", "visibility-gap", "unused-structure", "proposed-change"];
|
|
9
|
+
const PRIORITIES = ["low", "medium", "high"];
|
|
10
|
+
const STAGES = ["investigate", "plan-next", "later", "done"];
|
|
11
|
+
const EDITABLE = ["title", "outcome", "category", "priority", "assigneeId", "stage"];
|
|
12
|
+
function isRecord(value) {
|
|
13
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
function requiredText(body, key, max = 500) {
|
|
16
|
+
const value = body[key];
|
|
17
|
+
if (typeof value !== "string" || !value.trim())
|
|
18
|
+
throw new ApiError(400, "VALIDATION", `${key} is required`);
|
|
19
|
+
if (value.length > max)
|
|
20
|
+
throw new ApiError(400, "VALIDATION", `${key} is longer than ${max} characters`);
|
|
21
|
+
return value.trim();
|
|
22
|
+
}
|
|
23
|
+
function oneOf(value, allowed, key) {
|
|
24
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
25
|
+
throw new ApiError(400, "VALIDATION", `${key} must be one of ${allowed.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function targetOf(raw) {
|
|
30
|
+
if (!isRecord(raw))
|
|
31
|
+
throw new ApiError(400, "VALIDATION", "target is required");
|
|
32
|
+
const str = (key) => requiredText(raw, key, 200);
|
|
33
|
+
switch (raw.kind) {
|
|
34
|
+
case "object-type":
|
|
35
|
+
return { kind: "object-type", objectType: str("objectType") };
|
|
36
|
+
case "content-type":
|
|
37
|
+
return { kind: "content-type", objectType: str("objectType"), contentType: str("contentType") };
|
|
38
|
+
case "relationship-pair":
|
|
39
|
+
return {
|
|
40
|
+
kind: "relationship-pair",
|
|
41
|
+
definitionId: str("definitionId"),
|
|
42
|
+
fromObjectType: str("fromObjectType"),
|
|
43
|
+
toObjectType: str("toObjectType"),
|
|
44
|
+
};
|
|
45
|
+
default:
|
|
46
|
+
throw new ApiError(400, "VALIDATION", "target.kind must be object-type, content-type, or relationship-pair");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** `If-Match: "3"` → 3. Absent → null. */
|
|
50
|
+
function ifMatchOf(req) {
|
|
51
|
+
const raw = req.headers["if-match"];
|
|
52
|
+
const value = (Array.isArray(raw) ? raw[0] : raw)?.trim();
|
|
53
|
+
if (!value)
|
|
54
|
+
return null;
|
|
55
|
+
const match = /^(?:W\/)?"?(\d+)"?$/.exec(value);
|
|
56
|
+
if (!match)
|
|
57
|
+
throw new ApiError(400, "VALIDATION", 'If-Match must be the quoted item revision, for example "3"');
|
|
58
|
+
return Number(match[1]);
|
|
59
|
+
}
|
|
60
|
+
function encodeCursor(id) {
|
|
61
|
+
return Buffer.from(id, "utf8").toString("base64url");
|
|
62
|
+
}
|
|
63
|
+
function decodeCursor(raw) {
|
|
64
|
+
if (!raw)
|
|
65
|
+
return undefined;
|
|
66
|
+
const id = Buffer.from(raw, "base64url").toString("utf8");
|
|
67
|
+
if (!id.startsWith("pln_"))
|
|
68
|
+
throw new ApiError(400, "VALIDATION", "cursor does not belong to this query");
|
|
69
|
+
return id;
|
|
70
|
+
}
|
|
71
|
+
export function registerPlanningRoutes(app, deps) {
|
|
72
|
+
function storeOrThrow() {
|
|
73
|
+
if (!deps.planning) {
|
|
74
|
+
throw capabilityUnavailable("planning", "planning storage is not configured (ASSISTANT_MONGO_URI or MONGO_URI)");
|
|
75
|
+
}
|
|
76
|
+
return deps.planning;
|
|
77
|
+
}
|
|
78
|
+
function assigneesFor(orgId) {
|
|
79
|
+
return deps.assignees(orgId);
|
|
80
|
+
}
|
|
81
|
+
function assigneeView(orgId, id) {
|
|
82
|
+
if (id === null)
|
|
83
|
+
return { id: null, name: "Unassigned", kind: "unassigned" };
|
|
84
|
+
const known = assigneesFor(orgId)?.find((item) => item.id === id);
|
|
85
|
+
return known ? { id, name: known.name, kind: known.kind ?? "person" } : { id, name: id, kind: "unknown" };
|
|
86
|
+
}
|
|
87
|
+
function checkAssignee(orgId, value) {
|
|
88
|
+
if (value === null || value === undefined)
|
|
89
|
+
return null;
|
|
90
|
+
if (typeof value !== "string" || !assigneesFor(orgId)?.some((item) => item.id === value)) {
|
|
91
|
+
throw new ApiError(400, "ASSIGNEE_UNKNOWN", `assignee ${String(value)} is not in the option list for this org`);
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
async function writeScope(req) {
|
|
96
|
+
const scope = await deps.scopeFor(req, { agents: "optional" });
|
|
97
|
+
storeOrThrow();
|
|
98
|
+
const { claims } = await deps.authenticate(req);
|
|
99
|
+
if (claims && !tokenHasFeature(claims, PLANNING_WRITE_FEATURE, scope.orgId)) {
|
|
100
|
+
throw new ApiError(403, "PLANNING_FORBIDDEN", `planning writes need the ${PLANNING_WRITE_FEATURE} token feature for org ${scope.orgId}`);
|
|
101
|
+
}
|
|
102
|
+
return scope;
|
|
103
|
+
}
|
|
104
|
+
async function catalogFor(scope, needPairs, gaps) {
|
|
105
|
+
if (scope.agentIds.length === 0) {
|
|
106
|
+
gaps.push({ code: "TARGET_STATE_UNKNOWN", category: "unavailable", orgId: scope.orgId, agentIds: [], message: "no agents are recorded for this org, so targets cannot be checked", retryable: false });
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const objectTypes = await deps.loadCatalog(deps.upstream, scope);
|
|
111
|
+
let pairs = null;
|
|
112
|
+
if (needPairs) {
|
|
113
|
+
const definitions = await loadDefinitions(deps.upstream, scope, objectTypes);
|
|
114
|
+
pairs = new Set(definitions.definitions.flatMap((definition) => definition.objectTypes.map((pair) => `${definition.id}\u0000${pair.fromObjectType}\u0000${pair.toObjectType}`)));
|
|
115
|
+
}
|
|
116
|
+
return { objectTypes, pairs };
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
gaps.push({ code: "TARGET_STATE_UNKNOWN", category: "unavailable", orgId: scope.orgId, agentIds: scope.agentIds, message: `catalog could not be read (${err instanceof Error ? err.message : String(err)})`, retryable: true });
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function targetState(target, catalog) {
|
|
124
|
+
if (!catalog)
|
|
125
|
+
return "unknown";
|
|
126
|
+
if (target.kind === "relationship-pair") {
|
|
127
|
+
if (!catalog.pairs)
|
|
128
|
+
return "unknown";
|
|
129
|
+
return catalog.pairs.has(`${target.definitionId}\u0000${target.fromObjectType}\u0000${target.toObjectType}`)
|
|
130
|
+
? "in-catalog"
|
|
131
|
+
: "not-in-catalog";
|
|
132
|
+
}
|
|
133
|
+
const view = catalog.objectTypes.find((item) => item.id === target.objectType);
|
|
134
|
+
if (!view)
|
|
135
|
+
return "not-in-catalog";
|
|
136
|
+
if (target.kind === "object-type")
|
|
137
|
+
return "in-catalog";
|
|
138
|
+
if (view.resolution === "conflict")
|
|
139
|
+
return "unknown";
|
|
140
|
+
return view.contentTypes.some((ct) => ct.id === target.contentType) ? "in-catalog" : "not-in-catalog";
|
|
141
|
+
}
|
|
142
|
+
function present(orgId, item, catalog) {
|
|
143
|
+
const { assigneeId, ...rest } = item;
|
|
144
|
+
return { ...rest, assigneeId, assignee: assigneeView(orgId, assigneeId), targetState: targetState(item.target, catalog) };
|
|
145
|
+
}
|
|
146
|
+
async function presentOne(scope, item) {
|
|
147
|
+
const gaps = [];
|
|
148
|
+
const catalog = await catalogFor(scope, item.target.kind === "relationship-pair", gaps);
|
|
149
|
+
return { item: present(scope.orgId, item, catalog), gaps };
|
|
150
|
+
}
|
|
151
|
+
function sendItem(reply, scope, body, status = 200) {
|
|
152
|
+
reply.header("etag", `"${body.item.revision}"`);
|
|
153
|
+
return reply.status(status).send({ scope: scopeBody(scope), item: body.item, gaps: body.gaps });
|
|
154
|
+
}
|
|
155
|
+
async function conflict(scope, current, message) {
|
|
156
|
+
if (!current)
|
|
157
|
+
throw new ApiError(404, "READ_NOT_FOUND", "planning item not found");
|
|
158
|
+
const { item } = await presentOne(scope, current);
|
|
159
|
+
throw new ApiError(409, "PLANNING_CONFLICT", message, { current: item, headers: { etag: `"${current.revision}"` } });
|
|
160
|
+
}
|
|
161
|
+
async function applyChange(req, reply, changes, ifMatch) {
|
|
162
|
+
const scope = await writeScope(req);
|
|
163
|
+
const store = storeOrThrow();
|
|
164
|
+
const { itemId } = req.params;
|
|
165
|
+
const expected = ifMatchOf(req);
|
|
166
|
+
if (expected === null && ifMatch === "required") {
|
|
167
|
+
await conflict(scope, await store.get(scope.orgId, itemId), "If-Match with the current revision is required");
|
|
168
|
+
}
|
|
169
|
+
const result = await store.update(scope.orgId, itemId, expected, changes, scope.caller);
|
|
170
|
+
if (!result.ok)
|
|
171
|
+
await conflict(scope, result.current, `revision ${expected} is not the current revision`);
|
|
172
|
+
if (!result.ok)
|
|
173
|
+
throw new ApiError(500, "INTERNAL", "unreachable");
|
|
174
|
+
return sendItem(reply, scope, await presentOne(scope, result.item));
|
|
175
|
+
}
|
|
176
|
+
app.get("/api/v1/planning/items", async (req) => {
|
|
177
|
+
const scope = await deps.scopeFor(req, { agents: "optional" });
|
|
178
|
+
const store = storeOrThrow();
|
|
179
|
+
const query = queryOf(req);
|
|
180
|
+
const archivedRaw = text(query.archived);
|
|
181
|
+
if (archivedRaw && archivedRaw !== "true" && archivedRaw !== "false") {
|
|
182
|
+
throw new ApiError(400, "VALIDATION", "archived must be true or false");
|
|
183
|
+
}
|
|
184
|
+
const assignee = text(query.assignee);
|
|
185
|
+
const filter = {
|
|
186
|
+
archived: archivedRaw === "true",
|
|
187
|
+
...(text(query.stage) ? { stage: oneOf(text(query.stage), STAGES, "stage") } : {}),
|
|
188
|
+
...(text(query.priority) ? { priority: oneOf(text(query.priority), PRIORITIES, "priority") } : {}),
|
|
189
|
+
...(assignee ? { assigneeId: assignee === "unassigned" || assignee === "null" ? null : assignee } : {}),
|
|
190
|
+
...(text(query.objectType) ? { objectType: text(query.objectType) } : {}),
|
|
191
|
+
...(text(query.contentType) ? { contentType: text(query.contentType) } : {}),
|
|
192
|
+
...(text(query.definitionId) ? { definitionId: text(query.definitionId) } : {}),
|
|
193
|
+
};
|
|
194
|
+
const limit = limitOf(query.limit);
|
|
195
|
+
const page = await store.list(scope.orgId, filter, { limit, after: decodeCursor(text(query.cursor)) });
|
|
196
|
+
const gaps = [];
|
|
197
|
+
const catalog = await catalogFor(scope, page.items.some((item) => item.target.kind === "relationship-pair"), gaps);
|
|
198
|
+
return {
|
|
199
|
+
scope: scopeBody(scope),
|
|
200
|
+
items: page.items.map((item) => present(scope.orgId, item, catalog)),
|
|
201
|
+
pageInfo: { complete: !page.next, ...(page.next ? { nextCursor: encodeCursor(page.next) } : {}), limit },
|
|
202
|
+
gaps,
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
app.post("/api/v1/planning/items", async (req, reply) => {
|
|
206
|
+
const scope = await writeScope(req);
|
|
207
|
+
const store = storeOrThrow();
|
|
208
|
+
const body = isRecord(req.body) ? req.body : null;
|
|
209
|
+
if (!body)
|
|
210
|
+
throw new ApiError(400, "VALIDATION", "body must be a JSON object");
|
|
211
|
+
const now = new Date().toISOString();
|
|
212
|
+
const clientKey = body.clientKey === undefined || body.clientKey === null ? undefined : requiredText(body, "clientKey", 200);
|
|
213
|
+
const item = {
|
|
214
|
+
id: newPlanningId(),
|
|
215
|
+
orgId: scope.orgId,
|
|
216
|
+
title: requiredText(body, "title", 200),
|
|
217
|
+
outcome: requiredText(body, "outcome", 2000),
|
|
218
|
+
target: targetOf(body.target),
|
|
219
|
+
category: oneOf(body.category, CATEGORIES, "category"),
|
|
220
|
+
priority: oneOf(body.priority, PRIORITIES, "priority"),
|
|
221
|
+
assigneeId: checkAssignee(scope.orgId, body.assigneeId),
|
|
222
|
+
stage: body.stage === undefined ? "investigate" : oneOf(body.stage, STAGES, "stage"),
|
|
223
|
+
archived: false,
|
|
224
|
+
revision: 1,
|
|
225
|
+
createdBy: scope.caller,
|
|
226
|
+
createdAt: now,
|
|
227
|
+
updatedBy: scope.caller,
|
|
228
|
+
updatedAt: now,
|
|
229
|
+
evidence: body.evidence ?? null,
|
|
230
|
+
...(clientKey ? { clientKey } : {}),
|
|
231
|
+
};
|
|
232
|
+
const result = await store.insert(scope.orgId, item);
|
|
233
|
+
return sendItem(reply, scope, await presentOne(scope, result.item), result.created ? 201 : 200);
|
|
234
|
+
});
|
|
235
|
+
app.get("/api/v1/planning/items/:itemId", async (req, reply) => {
|
|
236
|
+
const scope = await deps.scopeFor(req, { agents: "optional" });
|
|
237
|
+
const store = storeOrThrow();
|
|
238
|
+
const { itemId } = req.params;
|
|
239
|
+
const item = await store.get(scope.orgId, itemId);
|
|
240
|
+
if (!item)
|
|
241
|
+
throw new ApiError(404, "READ_NOT_FOUND", `planning item ${itemId} not found`);
|
|
242
|
+
const etag = `"${item.revision}"`;
|
|
243
|
+
const inm = req.headers["if-none-match"];
|
|
244
|
+
if (typeof inm === "string" && inm.split(",").map((v) => v.trim().replace(/^W\//, "")).includes(etag)) {
|
|
245
|
+
reply.header("etag", etag);
|
|
246
|
+
return reply.code(304).send();
|
|
247
|
+
}
|
|
248
|
+
return sendItem(reply, scope, await presentOne(scope, item));
|
|
249
|
+
});
|
|
250
|
+
app.patch("/api/v1/planning/items/:itemId", async (req, reply) => {
|
|
251
|
+
const body = isRecord(req.body) ? req.body : null;
|
|
252
|
+
if (!body)
|
|
253
|
+
throw new ApiError(400, "VALIDATION", "body must be a JSON object");
|
|
254
|
+
if ("evidence" in body || "target" in body) {
|
|
255
|
+
throw new ApiError(400, "VALIDATION", "evidence and target cannot be edited. Changing the target is a new item.");
|
|
256
|
+
}
|
|
257
|
+
const unknown = Object.keys(body).filter((key) => !EDITABLE.includes(key));
|
|
258
|
+
if (unknown.length > 0)
|
|
259
|
+
throw new ApiError(400, "VALIDATION", `cannot edit ${unknown.join(", ")}`);
|
|
260
|
+
const scope = await deps.scopeFor(req, { agents: "optional" });
|
|
261
|
+
const changes = {};
|
|
262
|
+
if ("title" in body)
|
|
263
|
+
changes.title = requiredText(body, "title", 200);
|
|
264
|
+
if ("outcome" in body)
|
|
265
|
+
changes.outcome = requiredText(body, "outcome", 2000);
|
|
266
|
+
if ("category" in body)
|
|
267
|
+
changes.category = oneOf(body.category, CATEGORIES, "category");
|
|
268
|
+
if ("priority" in body)
|
|
269
|
+
changes.priority = oneOf(body.priority, PRIORITIES, "priority");
|
|
270
|
+
if ("stage" in body)
|
|
271
|
+
changes.stage = oneOf(body.stage, STAGES, "stage");
|
|
272
|
+
if ("assigneeId" in body)
|
|
273
|
+
changes.assigneeId = checkAssignee(scope.orgId, body.assigneeId);
|
|
274
|
+
if (Object.keys(changes).length === 0)
|
|
275
|
+
throw new ApiError(400, "VALIDATION", "nothing to change");
|
|
276
|
+
return applyChange(req, reply, changes, "required");
|
|
277
|
+
});
|
|
278
|
+
app.post("/api/v1/planning/items/:itemId/stage", async (req, reply) => {
|
|
279
|
+
const body = isRecord(req.body) ? req.body : {};
|
|
280
|
+
return applyChange(req, reply, { stage: oneOf(body.stage, STAGES, "stage") }, "required");
|
|
281
|
+
});
|
|
282
|
+
app.post("/api/v1/planning/items/:itemId/archive", async (req, reply) => applyChange(req, reply, { archived: true }, "optional"));
|
|
283
|
+
app.post("/api/v1/planning/items/:itemId/reopen", async (req, reply) => applyChange(req, reply, { archived: false, stage: "investigate" }, "optional"));
|
|
284
|
+
app.get("/api/v1/planning/assignees", async (req) => {
|
|
285
|
+
const scope = await deps.scopeFor(req, { agents: "none" });
|
|
286
|
+
storeOrThrow();
|
|
287
|
+
const options = assigneesFor(scope.orgId);
|
|
288
|
+
return {
|
|
289
|
+
configured: options !== null,
|
|
290
|
+
assignees: [
|
|
291
|
+
{ id: null, name: "Unassigned", kind: "unassigned" },
|
|
292
|
+
...(options ?? []).map((item) => ({ id: item.id, name: item.name, kind: item.kind ?? "person" })),
|
|
293
|
+
],
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=planning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planning.js","sourceRoot":"","sources":["../../src/v1/planning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FieldView } from "../catalog.js";
|
|
2
|
+
import { type ResolvedRecord } from "../refs.js";
|
|
3
|
+
import type { CensusSnapshot } from "./census.js";
|
|
4
|
+
export type RefsMode = "expand" | "status";
|
|
5
|
+
export declare function refsModeOf(raw: unknown, fallback: RefsMode): RefsMode;
|
|
6
|
+
/**
|
|
7
|
+
* Wrap every reference value with a `status`.
|
|
8
|
+
* `resolved` carries the target; `missing` was looked up and has no current head;
|
|
9
|
+
* `unresolved` was not looked up (target object type outside the catalog, or past the batch limit).
|
|
10
|
+
*/
|
|
11
|
+
export declare function wrapReferenceStatus(data: unknown, fields: FieldView[], resolved: ReadonlyMap<string, ResolvedRecord>, attempted: ReadonlySet<string>): unknown;
|
|
12
|
+
/** `total`, `totalStatus`, and `pageInfo.complete` for a directory page. */
|
|
13
|
+
export declare function recordsListExtras(objectType: string, nextCursor: string | null, census: CensusSnapshot | null): {
|
|
14
|
+
total: number | null;
|
|
15
|
+
totalStatus: "exact" | "unavailable";
|
|
16
|
+
complete: boolean;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=records.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/v1/records.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAsC,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3C,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAIrE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,SAAS,EAAE,EACnB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EAC7C,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,GAC7B,OAAO,CAeT;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,EAAE,cAAc,GAAG,IAAI,GAC5B;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,OAAO,GAAG,aAAa,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CASnF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ApiError } from "../errors.js";
|
|
2
|
+
import { referenceKey, rewriteReferenceData } from "../refs.js";
|
|
3
|
+
export function refsModeOf(raw, fallback) {
|
|
4
|
+
if (raw === undefined || raw === "")
|
|
5
|
+
return fallback;
|
|
6
|
+
if (raw === "expand" || raw === "status")
|
|
7
|
+
return raw;
|
|
8
|
+
throw new ApiError(400, "VALIDATION", "refs must be expand or status");
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Wrap every reference value with a `status`.
|
|
12
|
+
* `resolved` carries the target; `missing` was looked up and has no current head;
|
|
13
|
+
* `unresolved` was not looked up (target object type outside the catalog, or past the batch limit).
|
|
14
|
+
*/
|
|
15
|
+
export function wrapReferenceStatus(data, fields, resolved, attempted) {
|
|
16
|
+
return rewriteReferenceData(data, fields, (id, objectType) => {
|
|
17
|
+
const key = referenceKey(objectType, id);
|
|
18
|
+
const hit = resolved.get(key);
|
|
19
|
+
if (hit) {
|
|
20
|
+
return {
|
|
21
|
+
status: "resolved",
|
|
22
|
+
recordId: hit.recordId,
|
|
23
|
+
objectType: hit.objectType,
|
|
24
|
+
contentType: hit.contentType,
|
|
25
|
+
data: structuredClone(hit.data),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return { status: attempted.has(key) ? "missing" : "unresolved", value: id, objectType };
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** `total`, `totalStatus`, and `pageInfo.complete` for a directory page. */
|
|
32
|
+
export function recordsListExtras(objectType, nextCursor, census) {
|
|
33
|
+
const entry = census?.objectTypes.find((item) => item.objectType === objectType);
|
|
34
|
+
const records = entry?.records;
|
|
35
|
+
const exact = records && records.status === "exact" ? records.value : null;
|
|
36
|
+
return {
|
|
37
|
+
total: exact,
|
|
38
|
+
totalStatus: exact === null ? "unavailable" : "exact",
|
|
39
|
+
complete: nextCursor === null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/v1/records.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAuB,MAAM,YAAY,CAAC;AAKrF,MAAM,UAAU,UAAU,CAAC,GAAY,EAAE,QAAkB;IACzD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IACrD,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACrD,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,YAAY,EAAE,+BAA+B,CAAC,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAa,EACb,MAAmB,EACnB,QAA6C,EAC7C,SAA8B;IAE9B,OAAO,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE;QAC3D,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,EAAE,CAAC;YACR,OAAO;gBACL,MAAM,EAAE,UAAU;gBAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;aAChC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAC/B,UAAkB,EAClB,UAAyB,EACzB,MAA6B;IAE7B,MAAM,KAAK,GAAG,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO;QACrD,QAAQ,EAAE,UAAU,KAAK,IAAI;KAC9B,CAAC;AACJ,CAAC"}
|