dxcomplete 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.
- package/.env.example +11 -0
- package/README.md +215 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +212 -0
- package/dist/http/server.d.ts +7 -0
- package/dist/http/server.js +236 -0
- package/dist/http/service.d.ts +7 -0
- package/dist/http/service.js +725 -0
- package/dist/init.d.ts +13 -0
- package/dist/init.js +128 -0
- package/dist/install-manifest.d.ts +25 -0
- package/dist/install-manifest.js +96 -0
- package/dist/mcp/docs.d.ts +98 -0
- package/dist/mcp/docs.js +438 -0
- package/dist/mcp/server.d.ts +20 -0
- package/dist/mcp/server.js +2345 -0
- package/dist/package-root.d.ts +2 -0
- package/dist/package-root.js +28 -0
- package/dist/runtime/actor.d.ts +14 -0
- package/dist/runtime/actor.js +42 -0
- package/dist/runtime/auth.d.ts +162 -0
- package/dist/runtime/auth.js +394 -0
- package/dist/runtime/check.d.ts +7 -0
- package/dist/runtime/check.js +16 -0
- package/dist/runtime/config.d.ts +17 -0
- package/dist/runtime/config.js +93 -0
- package/dist/runtime/mongo.d.ts +9 -0
- package/dist/runtime/mongo.js +56 -0
- package/dist/runtime/records.d.ts +336 -0
- package/dist/runtime/records.js +1463 -0
- package/dist/runtime/workspace.d.ts +19 -0
- package/dist/runtime/workspace.js +102 -0
- package/dist/upgrade.d.ts +20 -0
- package/dist/upgrade.js +246 -0
- package/dist/validate.d.ts +10 -0
- package/dist/validate.js +119 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +12 -0
- package/docs/codex-integration.md +29 -0
- package/docs/cost-model.md +61 -0
- package/docs/decision-basis.md +57 -0
- package/docs/diagrams.md +31 -0
- package/docs/glossary.md +147 -0
- package/docs/index.md +60 -0
- package/docs/model.md +110 -0
- package/docs/open-questions.md +61 -0
- package/docs/roles.md +42 -0
- package/docs/taxonomy.md +96 -0
- package/docs/workflows.md +60 -0
- package/package.json +62 -0
- package/scripts/check-env-surface.mjs +136 -0
- package/scripts/check-public-copy.mjs +263 -0
- package/scripts/check-service-boundary.mjs +63 -0
- package/scripts/dogfood-work-order.mjs +506 -0
- package/scripts/smoke-mcp-http.mjs +3572 -0
- package/src/cli.ts +268 -0
- package/src/http/server.ts +314 -0
- package/src/http/service.ts +934 -0
- package/src/init.ts +227 -0
- package/src/install-manifest.ts +144 -0
- package/src/mcp/docs.ts +557 -0
- package/src/mcp/server.ts +3525 -0
- package/src/package-root.ts +31 -0
- package/src/runtime/actor.ts +61 -0
- package/src/runtime/auth.ts +673 -0
- package/src/runtime/check.ts +18 -0
- package/src/runtime/config.ts +128 -0
- package/src/runtime/mongo.ts +89 -0
- package/src/runtime/records.ts +2303 -0
- package/src/runtime/workspace.ts +155 -0
- package/src/upgrade.ts +356 -0
- package/src/validate.ts +139 -0
- package/src/version.ts +16 -0
- package/templates/github/workflows/dxcomplete.yml +16 -0
- package/templates/next/pages/api/auth/callback/google.js +12 -0
- package/templates/next/pages/api/dxcomplete/[...path].js +12 -0
- package/templates/next/pages/api/dxcomplete.js +12 -0
- package/templates/next/pages/api/mcp.js +12 -0
- package/templates/next/vercel.json +18 -0
- package/templates/process/README.md +38 -0
- package/templates/process/controls.yml +113 -0
- package/templates/process/cost-model.yml +71 -0
- package/templates/process/decision-basis.yml +53 -0
- package/templates/process/decisions/.gitkeep +1 -0
- package/templates/process/diagrams/00-decision-basis.mmd +24 -0
- package/templates/process/diagrams/00-overview.mmd +20 -0
- package/templates/process/diagrams/01-intake-triage.mmd +20 -0
- package/templates/process/diagrams/02-product-definition.mmd +14 -0
- package/templates/process/diagrams/03-engineering-execution.mmd +15 -0
- package/templates/process/diagrams/04-qa-verification.mmd +12 -0
- package/templates/process/diagrams/05-product-validation.mmd +12 -0
- package/templates/process/diagrams/06-change-release-control.mmd +16 -0
- package/templates/process/diagrams/07-deployment-operations.mmd +16 -0
- package/templates/process/diagrams/08-support-incident-management.mmd +16 -0
- package/templates/process/diagrams/09-problem-improvement.mmd +14 -0
- package/templates/process/diagrams/10-risk-control-management.mmd +14 -0
- package/templates/process/diagrams/11-audit-evidence-capture.mmd +13 -0
- package/templates/process/evidence/.gitkeep +1 -0
- package/templates/process/risks/.gitkeep +1 -0
- package/templates/process/roles.yml +96 -0
- package/templates/process/taxonomy.yml +514 -0
- package/templates/process/workflows.yml +210 -0
- package/website/.well-known/oauth-authorization-server +22 -0
- package/website/.well-known/oauth-protected-resource/api/dxcomplete/mcp +10 -0
- package/website/.well-known/oauth-protected-resource/api/mcp +10 -0
- package/website/README.md +12 -0
- package/website/app.js +36 -0
- package/website/flow.html +85 -0
- package/website/glossary.html +280 -0
- package/website/index.html +90 -0
- package/website/objects.html +287 -0
- package/website/outcomes.html +117 -0
- package/website/phase-build.html +101 -0
- package/website/phase-elicit.html +102 -0
- package/website/phase-go-live.html +103 -0
- package/website/phase-measure.html +93 -0
- package/website/phase-operate.html +102 -0
- package/website/phase-orient.html +92 -0
- package/website/phase-weigh.html +98 -0
- package/website/roles.html +52 -0
- package/website/styles.css +1169 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { constants as fsConstants } from "node:fs";
|
|
2
|
+
import { access, readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export class RuntimeConfigError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "RuntimeConfigError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
const DEFAULT_ENV_FILE = ".env.local";
|
|
11
|
+
const DEFAULT_DATABASE_NAME = "dxcomplete";
|
|
12
|
+
export async function loadRuntimeConfig(options = {}) {
|
|
13
|
+
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
14
|
+
const envFilePath = await resolveEnvFile(cwd, options.envFile);
|
|
15
|
+
const fileEnv = envFilePath ? await parseEnvFile(envFilePath) : {};
|
|
16
|
+
const env = {
|
|
17
|
+
...fileEnv,
|
|
18
|
+
...(options.env ?? process.env)
|
|
19
|
+
};
|
|
20
|
+
const mongodbUri = readRequiredEnv(env, "DXC_MONGODB_URI");
|
|
21
|
+
const databaseName = readOptionalEnv(env, "DXC_DATABASE_NAME") ?? DEFAULT_DATABASE_NAME;
|
|
22
|
+
const googleClientId = readOptionalEnv(env, "DXC_GOOGLE_CLIENT_ID");
|
|
23
|
+
const googleClientSecret = readOptionalEnv(env, "DXC_GOOGLE_CLIENT_SECRET");
|
|
24
|
+
const serviceProvisioningSecret = readOptionalEnv(env, "DXC_SERVICE_PROVISIONING_SECRET");
|
|
25
|
+
return {
|
|
26
|
+
mongodbUri,
|
|
27
|
+
databaseName,
|
|
28
|
+
...(googleClientId ? { googleClientId } : {}),
|
|
29
|
+
...(googleClientSecret ? { googleClientSecret } : {}),
|
|
30
|
+
...(serviceProvisioningSecret ? { serviceProvisioningSecret } : {}),
|
|
31
|
+
envFilePath
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function resolveEnvFile(cwd, envFile) {
|
|
35
|
+
if (envFile) {
|
|
36
|
+
const explicitPath = path.resolve(cwd, envFile);
|
|
37
|
+
if (!(await fileExists(explicitPath))) {
|
|
38
|
+
throw new RuntimeConfigError(`Env file not found: ${explicitPath}`);
|
|
39
|
+
}
|
|
40
|
+
return explicitPath;
|
|
41
|
+
}
|
|
42
|
+
const defaultPath = path.join(cwd, DEFAULT_ENV_FILE);
|
|
43
|
+
return (await fileExists(defaultPath)) ? defaultPath : undefined;
|
|
44
|
+
}
|
|
45
|
+
async function parseEnvFile(filePath) {
|
|
46
|
+
const content = await readFile(filePath, "utf8");
|
|
47
|
+
const parsed = {};
|
|
48
|
+
for (const [index, rawLine] of content.split(/\r?\n/).entries()) {
|
|
49
|
+
const trimmed = rawLine.trim();
|
|
50
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const line = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed;
|
|
54
|
+
const equalsIndex = line.indexOf("=");
|
|
55
|
+
if (equalsIndex === -1) {
|
|
56
|
+
throw new RuntimeConfigError(`Invalid env line ${index + 1} in ${filePath}. Expected KEY=value.`);
|
|
57
|
+
}
|
|
58
|
+
const key = line.slice(0, equalsIndex).trim();
|
|
59
|
+
const value = line.slice(equalsIndex + 1).trim();
|
|
60
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
|
|
61
|
+
throw new RuntimeConfigError(`Invalid env key "${key}" on line ${index + 1} in ${filePath}.`);
|
|
62
|
+
}
|
|
63
|
+
parsed[key] = unquote(value);
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
function readRequiredEnv(env, key) {
|
|
68
|
+
const value = readOptionalEnv(env, key);
|
|
69
|
+
if (!value) {
|
|
70
|
+
throw new RuntimeConfigError(`${key} is required. Create .env.local from .env.example or export ${key} before running this command.`);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
function readOptionalEnv(env, key) {
|
|
75
|
+
const value = env[key]?.trim();
|
|
76
|
+
return value ? value : undefined;
|
|
77
|
+
}
|
|
78
|
+
function unquote(value) {
|
|
79
|
+
if ((value.startsWith("\"") && value.endsWith("\"")) ||
|
|
80
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
81
|
+
return value.slice(1, -1);
|
|
82
|
+
}
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
async function fileExists(filePath) {
|
|
86
|
+
try {
|
|
87
|
+
await access(filePath, fsConstants.F_OK);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MongoClient, type Db } from "mongodb";
|
|
2
|
+
import { type RuntimeConfig, type RuntimeOptions } from "./config.js";
|
|
3
|
+
export type DxRuntime = {
|
|
4
|
+
config: RuntimeConfig;
|
|
5
|
+
client: MongoClient;
|
|
6
|
+
db: Db;
|
|
7
|
+
close: () => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
export declare function connectRuntime(options?: RuntimeOptions): Promise<DxRuntime>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MongoClient } from "mongodb";
|
|
2
|
+
import { OAUTH_AUTH_REQUESTS_COLLECTION, OAUTH_CLIENTS_COLLECTION, OAUTH_CODES_COLLECTION, OAUTH_TOKENS_COLLECTION, WORKSPACE_SERVICE_CLIENTS_COLLECTION, WORKSPACE_MEMBERSHIPS_COLLECTION } from "./auth.js";
|
|
3
|
+
import { loadRuntimeConfig } from "./config.js";
|
|
4
|
+
import { DXCOMPLETE_TICKET_COLLECTION_NAME, INDEX_COLLECTION_NAMES, READABLE_ID_COLLECTION_NAMES, READABLE_ID_SEQUENCES_COLLECTION, migrateLegacyIntakeItemsToDxcompleteTickets } from "./records.js";
|
|
5
|
+
export async function connectRuntime(options = {}) {
|
|
6
|
+
const config = await loadRuntimeConfig(options);
|
|
7
|
+
const client = new MongoClient(config.mongodbUri, {
|
|
8
|
+
serverSelectionTimeoutMS: 10000
|
|
9
|
+
});
|
|
10
|
+
await client.connect();
|
|
11
|
+
const db = client.db(config.databaseName);
|
|
12
|
+
await db.command({ ping: 1 });
|
|
13
|
+
await migrateLegacyIntakeItemsToDxcompleteTickets(db);
|
|
14
|
+
await ensureIndexes(db);
|
|
15
|
+
return {
|
|
16
|
+
config,
|
|
17
|
+
client,
|
|
18
|
+
db,
|
|
19
|
+
close: () => client.close()
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function ensureIndexes(db) {
|
|
23
|
+
await Promise.all(INDEX_COLLECTION_NAMES.map(async (collectionName) => {
|
|
24
|
+
const collection = db.collection(collectionName);
|
|
25
|
+
await collection.createIndex({ recordType: 1, createdAt: -1 });
|
|
26
|
+
await collection.createIndex({ workspaceId: 1, recordType: 1, createdAt: -1 });
|
|
27
|
+
await collection.createIndex({ "links.toId": 1 });
|
|
28
|
+
await collection.createIndex({ workspaceId: 1, "links.toId": 1 });
|
|
29
|
+
if (READABLE_ID_COLLECTION_NAMES.includes(collectionName)) {
|
|
30
|
+
await collection.createIndex({ workspaceId: 1, readableId: 1 }, {
|
|
31
|
+
unique: true,
|
|
32
|
+
partialFilterExpression: { readableId: { $exists: true } }
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (collectionName === DXCOMPLETE_TICKET_COLLECTION_NAME) {
|
|
36
|
+
await collection.createIndex({ "fields.ownerActorId": 1, archivedAt: 1, updatedAt: -1 });
|
|
37
|
+
await collection.createIndex({ "fields.entries.addressedToActorId": 1, "fields.entries.readAt": 1 });
|
|
38
|
+
}
|
|
39
|
+
if (collectionName === "journal_entries") {
|
|
40
|
+
await collection.createIndex({ workspaceId: 1, "fields.kind": 1, archivedAt: 1, createdAt: 1 });
|
|
41
|
+
await collection.createIndex({ workspaceId: 1, archivedAt: 1, createdAt: 1 });
|
|
42
|
+
}
|
|
43
|
+
}));
|
|
44
|
+
await Promise.all([
|
|
45
|
+
db.collection(WORKSPACE_MEMBERSHIPS_COLLECTION).createIndex({ workspaceId: 1, email: 1 }, { unique: true }),
|
|
46
|
+
db.collection(WORKSPACE_MEMBERSHIPS_COLLECTION).createIndex({ provider: 1, providerSubject: 1 }),
|
|
47
|
+
db.collection(WORKSPACE_SERVICE_CLIENTS_COLLECTION).createIndex({ workspaceId: 1, clientId: 1 }, { unique: true }),
|
|
48
|
+
db.collection(WORKSPACE_SERVICE_CLIENTS_COLLECTION).createIndex({ clientId: 1 }, { unique: true }),
|
|
49
|
+
db.collection(OAUTH_CLIENTS_COLLECTION).createIndex({ clientId: 1 }, { unique: true }),
|
|
50
|
+
db.collection(OAUTH_AUTH_REQUESTS_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
|
|
51
|
+
db.collection(OAUTH_CODES_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
|
|
52
|
+
db.collection(OAUTH_TOKENS_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
|
|
53
|
+
db.collection(OAUTH_TOKENS_COLLECTION).createIndex({ workspaceId: 1, "actor.actorId": 1 }),
|
|
54
|
+
db.collection(READABLE_ID_SEQUENCES_COLLECTION).createIndex({ workspaceId: 1, recordType: 1 }, { unique: true })
|
|
55
|
+
]);
|
|
56
|
+
}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import type { Db } from "mongodb";
|
|
2
|
+
import type { ActorContext } from "./actor.js";
|
|
3
|
+
export declare const COLLECTION_NAMES: readonly ["workspaces", "statements", "journal_entries", "environments", "components", "estimates", "benefits", "expectations", "requirements", "tasks", "commitments", "deferrals", "changes", "decisions", "risks"];
|
|
4
|
+
export declare const LEGACY_COLLECTION_NAMES: readonly ["engagements", "initiatives", "service_charters", "cost_baselines", "cost_actuals", "benefit_measurements"];
|
|
5
|
+
export declare const DXCOMPLETE_TICKET_COLLECTION_NAME = "dxcomplete_tickets";
|
|
6
|
+
export declare const LEGACY_INTAKE_COLLECTION_NAME = "intake_items";
|
|
7
|
+
export declare const LEGACY_PRIVATE_COLLECTION_NAMES: readonly ["intake_items"];
|
|
8
|
+
export declare const INDEX_COLLECTION_NAMES: readonly ["workspaces", "statements", "journal_entries", "environments", "components", "estimates", "benefits", "expectations", "requirements", "tasks", "commitments", "deferrals", "changes", "decisions", "risks", "dxcomplete_tickets"];
|
|
9
|
+
export declare const LINK_SCAN_COLLECTION_NAMES: readonly ["workspaces", "statements", "journal_entries", "environments", "components", "estimates", "benefits", "expectations", "requirements", "tasks", "commitments", "deferrals", "changes", "decisions", "risks", "engagements", "initiatives", "service_charters", "cost_baselines", "cost_actuals", "benefit_measurements"];
|
|
10
|
+
export declare const READABLE_ID_SEQUENCES_COLLECTION = "readable_id_sequences";
|
|
11
|
+
export declare const READABLE_ID_TYPE_CODES: {
|
|
12
|
+
readonly statements: "STM";
|
|
13
|
+
readonly journal_entries: "JRN";
|
|
14
|
+
readonly environments: "ENV";
|
|
15
|
+
readonly components: "CMP";
|
|
16
|
+
readonly expectations: "EXP";
|
|
17
|
+
readonly requirements: "REQ";
|
|
18
|
+
readonly tasks: "TSK";
|
|
19
|
+
readonly commitments: "CMT";
|
|
20
|
+
readonly deferrals: "DFR";
|
|
21
|
+
readonly decisions: "DEC";
|
|
22
|
+
readonly changes: "CHG";
|
|
23
|
+
readonly risks: "RSK";
|
|
24
|
+
readonly estimates: "EST";
|
|
25
|
+
readonly benefits: "BFT";
|
|
26
|
+
};
|
|
27
|
+
export declare const READABLE_ID_COLLECTION_NAMES: ReadableIdCollectionName[];
|
|
28
|
+
export type CollectionName = (typeof COLLECTION_NAMES)[number];
|
|
29
|
+
export type ReadableIdCollectionName = keyof typeof READABLE_ID_TYPE_CODES;
|
|
30
|
+
export type PrivateCollectionName = typeof DXCOMPLETE_TICKET_COLLECTION_NAME;
|
|
31
|
+
export type RuntimeCollectionName = CollectionName | PrivateCollectionName | (typeof LEGACY_COLLECTION_NAMES)[number] | (typeof LEGACY_PRIVATE_COLLECTION_NAMES)[number];
|
|
32
|
+
export type RecordLink = {
|
|
33
|
+
toType: RuntimeCollectionName;
|
|
34
|
+
toId: string;
|
|
35
|
+
relationship: string;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
createdBy: string;
|
|
38
|
+
};
|
|
39
|
+
export type RecordEdge = RecordLink & {
|
|
40
|
+
fromType: RuntimeCollectionName;
|
|
41
|
+
fromId: string;
|
|
42
|
+
};
|
|
43
|
+
export type DxcRecord = {
|
|
44
|
+
_id: string;
|
|
45
|
+
recordType: RuntimeCollectionName;
|
|
46
|
+
readableId?: string;
|
|
47
|
+
workspaceId?: string;
|
|
48
|
+
title?: string;
|
|
49
|
+
summary?: string;
|
|
50
|
+
fields: Record<string, unknown>;
|
|
51
|
+
links: RecordLink[];
|
|
52
|
+
archivedAt?: string;
|
|
53
|
+
archivedBy?: string;
|
|
54
|
+
archiveReason?: string;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
createdBy: string;
|
|
57
|
+
updatedAt: string;
|
|
58
|
+
updatedBy: string;
|
|
59
|
+
};
|
|
60
|
+
export type ReviewableRecordType = "expectations" | "requirements";
|
|
61
|
+
export type ReviewNote = {
|
|
62
|
+
id: string;
|
|
63
|
+
body: string;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
createdBy: string;
|
|
66
|
+
important?: true;
|
|
67
|
+
};
|
|
68
|
+
export type RecordVersionSnapshot = {
|
|
69
|
+
title?: string;
|
|
70
|
+
summary?: string;
|
|
71
|
+
fields: Record<string, unknown>;
|
|
72
|
+
};
|
|
73
|
+
export type RecordVersionHistoryEntry = {
|
|
74
|
+
id: string;
|
|
75
|
+
fromVersion: number;
|
|
76
|
+
toVersion: number;
|
|
77
|
+
createdAt: string;
|
|
78
|
+
createdBy: string;
|
|
79
|
+
changedFields: string[];
|
|
80
|
+
previousSnapshot: RecordVersionSnapshot;
|
|
81
|
+
nextSnapshot: RecordVersionSnapshot;
|
|
82
|
+
revisionNote?: string;
|
|
83
|
+
};
|
|
84
|
+
export type ChangeEventType = "notice_given" | "veto_recorded" | "emergency_declared" | "decision_recorded" | "result_reported" | "recovery_recorded" | "plan_revised" | "note_added";
|
|
85
|
+
export type ChangeEvent = {
|
|
86
|
+
id: string;
|
|
87
|
+
eventType: ChangeEventType;
|
|
88
|
+
createdAt: string;
|
|
89
|
+
createdBy: string;
|
|
90
|
+
} & Record<string, unknown>;
|
|
91
|
+
export type DeferralEventType = "condition_addressed" | "condition_reopened" | "condition_note_added" | "deferral_resolved" | "deferral_abandoned";
|
|
92
|
+
export type DeferralCondition = {
|
|
93
|
+
id: string;
|
|
94
|
+
statement: string;
|
|
95
|
+
state: "open" | "addressed";
|
|
96
|
+
createdAt: string;
|
|
97
|
+
createdBy: string;
|
|
98
|
+
updatedAt: string;
|
|
99
|
+
updatedBy: string;
|
|
100
|
+
};
|
|
101
|
+
export type DeferralEvent = {
|
|
102
|
+
id: string;
|
|
103
|
+
eventType: DeferralEventType;
|
|
104
|
+
createdAt: string;
|
|
105
|
+
createdBy: string;
|
|
106
|
+
} & Record<string, unknown>;
|
|
107
|
+
export type DecisionEntryType = "argument" | "decision" | "note";
|
|
108
|
+
export type DecisionEntry = {
|
|
109
|
+
id: string;
|
|
110
|
+
entryType: DecisionEntryType;
|
|
111
|
+
body: string;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
createdBy: string;
|
|
114
|
+
decidedBy?: string;
|
|
115
|
+
rationale?: string;
|
|
116
|
+
};
|
|
117
|
+
export type TaskEntryType = "comment" | "status_change" | "note";
|
|
118
|
+
export type TaskStatus = "open" | "in_progress" | "blocked" | "done";
|
|
119
|
+
export type TaskEntry = {
|
|
120
|
+
id: string;
|
|
121
|
+
entryType: TaskEntryType;
|
|
122
|
+
body: string;
|
|
123
|
+
createdAt: string;
|
|
124
|
+
createdBy: string;
|
|
125
|
+
status?: TaskStatus;
|
|
126
|
+
};
|
|
127
|
+
export type JournalEntryKind = "note" | "summary";
|
|
128
|
+
export type AppendJournalNoteInput = {
|
|
129
|
+
workspaceId: string;
|
|
130
|
+
body: string;
|
|
131
|
+
tag?: string;
|
|
132
|
+
};
|
|
133
|
+
export type ReadJournalInput = {
|
|
134
|
+
workspaceId: string;
|
|
135
|
+
limit?: number;
|
|
136
|
+
includeArchived?: boolean;
|
|
137
|
+
};
|
|
138
|
+
export type ReadJournalResult = {
|
|
139
|
+
workspaceId: string;
|
|
140
|
+
readTier: "hot" | "cold";
|
|
141
|
+
compaction: {
|
|
142
|
+
activeRawNoteCount: number;
|
|
143
|
+
threshold: number;
|
|
144
|
+
recommended: boolean;
|
|
145
|
+
};
|
|
146
|
+
entries: DxcRecord[];
|
|
147
|
+
};
|
|
148
|
+
export type GetJournalEntryInput = {
|
|
149
|
+
workspaceId: string;
|
|
150
|
+
id: string;
|
|
151
|
+
};
|
|
152
|
+
export type AppendJournalSummaryInput = {
|
|
153
|
+
workspaceId: string;
|
|
154
|
+
body: string;
|
|
155
|
+
covers: string[];
|
|
156
|
+
tag?: string;
|
|
157
|
+
};
|
|
158
|
+
export type CreateRecordInput = {
|
|
159
|
+
id?: string;
|
|
160
|
+
workspaceId?: string;
|
|
161
|
+
title?: string;
|
|
162
|
+
summary?: string;
|
|
163
|
+
fields?: Record<string, unknown>;
|
|
164
|
+
allowManagedFields?: boolean;
|
|
165
|
+
};
|
|
166
|
+
export type UpdateRecordInput = {
|
|
167
|
+
recordType: CollectionName;
|
|
168
|
+
id: string;
|
|
169
|
+
workspaceId?: string;
|
|
170
|
+
title?: string;
|
|
171
|
+
summary?: string;
|
|
172
|
+
fields?: Record<string, unknown>;
|
|
173
|
+
unsetFields?: string[];
|
|
174
|
+
allowManagedFields?: boolean;
|
|
175
|
+
revisionNote?: string;
|
|
176
|
+
};
|
|
177
|
+
export type AppendReviewNoteInput = {
|
|
178
|
+
recordType: ReviewableRecordType;
|
|
179
|
+
id: string;
|
|
180
|
+
workspaceId: string;
|
|
181
|
+
body: string;
|
|
182
|
+
important?: boolean;
|
|
183
|
+
};
|
|
184
|
+
export type AppendChangeEventInput = {
|
|
185
|
+
workspaceId: string;
|
|
186
|
+
changeId: string;
|
|
187
|
+
eventType: ChangeEventType;
|
|
188
|
+
event: Record<string, unknown>;
|
|
189
|
+
};
|
|
190
|
+
export type AppendDeferralEventInput = {
|
|
191
|
+
workspaceId: string;
|
|
192
|
+
deferralId: string;
|
|
193
|
+
eventType: DeferralEventType;
|
|
194
|
+
event: Record<string, unknown>;
|
|
195
|
+
};
|
|
196
|
+
export type AppendDecisionEntryInput = {
|
|
197
|
+
workspaceId: string;
|
|
198
|
+
decisionId: string;
|
|
199
|
+
entryType: DecisionEntryType;
|
|
200
|
+
body: string;
|
|
201
|
+
decidedBy?: string;
|
|
202
|
+
rationale?: string;
|
|
203
|
+
};
|
|
204
|
+
export type AppendTaskEntryInput = {
|
|
205
|
+
workspaceId: string;
|
|
206
|
+
taskId: string;
|
|
207
|
+
entryType: TaskEntryType;
|
|
208
|
+
body: string;
|
|
209
|
+
status?: TaskStatus;
|
|
210
|
+
};
|
|
211
|
+
export type UnlinkRecordsInput = {
|
|
212
|
+
fromType: CollectionName;
|
|
213
|
+
fromId: string;
|
|
214
|
+
toType: CollectionName;
|
|
215
|
+
toId: string;
|
|
216
|
+
workspaceId?: string;
|
|
217
|
+
relationship?: string;
|
|
218
|
+
};
|
|
219
|
+
export type ArchiveRecordInput = {
|
|
220
|
+
recordType: CollectionName;
|
|
221
|
+
id: string;
|
|
222
|
+
workspaceId?: string;
|
|
223
|
+
reason?: string;
|
|
224
|
+
supersededByType?: CollectionName;
|
|
225
|
+
supersededById?: string;
|
|
226
|
+
};
|
|
227
|
+
export type LinkedRecordsResult = {
|
|
228
|
+
source: DxcRecord;
|
|
229
|
+
outbound: Array<{
|
|
230
|
+
edge: RecordEdge;
|
|
231
|
+
record: DxcRecord;
|
|
232
|
+
}>;
|
|
233
|
+
inbound: Array<{
|
|
234
|
+
edge: RecordEdge;
|
|
235
|
+
record: DxcRecord;
|
|
236
|
+
}>;
|
|
237
|
+
};
|
|
238
|
+
export type DxcompleteTicketEntryDirection = "submitter_entry" | "dxcomplete_reply";
|
|
239
|
+
export type DxcompleteTicketEntry = {
|
|
240
|
+
id: string;
|
|
241
|
+
body: string;
|
|
242
|
+
createdAt: string;
|
|
243
|
+
createdBy: string;
|
|
244
|
+
direction: DxcompleteTicketEntryDirection;
|
|
245
|
+
addressedToActorId?: string;
|
|
246
|
+
readAt?: string;
|
|
247
|
+
};
|
|
248
|
+
export type CreateDxcompleteTicketInput = {
|
|
249
|
+
title: string;
|
|
250
|
+
body: string;
|
|
251
|
+
};
|
|
252
|
+
export type AppendDxcompleteTicketInput = {
|
|
253
|
+
id: string;
|
|
254
|
+
body: string;
|
|
255
|
+
};
|
|
256
|
+
export type AppendDxcompleteTicketReplyInput = {
|
|
257
|
+
id: string;
|
|
258
|
+
body: string;
|
|
259
|
+
addressedToActorId: string;
|
|
260
|
+
};
|
|
261
|
+
export type ArchiveDxcompleteTicketInput = {
|
|
262
|
+
id: string;
|
|
263
|
+
};
|
|
264
|
+
export type ReadDxcompleteTicketInput = {
|
|
265
|
+
id: string;
|
|
266
|
+
};
|
|
267
|
+
export type DxcompleteTicketUnreadReplySummary = {
|
|
268
|
+
id: string;
|
|
269
|
+
createdAt: string;
|
|
270
|
+
createdBy: string;
|
|
271
|
+
direction: "dxcomplete_reply";
|
|
272
|
+
addressedToActorId?: string;
|
|
273
|
+
};
|
|
274
|
+
export type DxcompleteTicketUnreadReplyResult = {
|
|
275
|
+
ticketId: string;
|
|
276
|
+
title?: string;
|
|
277
|
+
updatedAt: string;
|
|
278
|
+
unreadReplyCount: number;
|
|
279
|
+
newestReplyAt?: string;
|
|
280
|
+
replies: DxcompleteTicketUnreadReplySummary[];
|
|
281
|
+
};
|
|
282
|
+
export declare const RUNTIME_ACTOR_ID = "dxcomplete-runtime";
|
|
283
|
+
export declare function assertCollectionName(value: string): CollectionName;
|
|
284
|
+
export declare function createRecord(db: Db, recordType: CollectionName, input: CreateRecordInput, actorId: string): Promise<DxcRecord>;
|
|
285
|
+
export declare function listRecords(db: Db, recordType: CollectionName, limit: number, options?: {
|
|
286
|
+
includeArchived?: boolean;
|
|
287
|
+
workspaceId?: string;
|
|
288
|
+
}): Promise<DxcRecord[]>;
|
|
289
|
+
export declare function getRecord(db: Db, recordType: RuntimeCollectionName, id: string, options?: {
|
|
290
|
+
workspaceId?: string;
|
|
291
|
+
allowAnyWorkspace?: boolean;
|
|
292
|
+
}): Promise<DxcRecord | null>;
|
|
293
|
+
export declare function listLinkedRecords(db: Db, input: {
|
|
294
|
+
recordType: CollectionName;
|
|
295
|
+
id: string;
|
|
296
|
+
workspaceId?: string;
|
|
297
|
+
direction?: "outbound" | "inbound" | "both";
|
|
298
|
+
relationship?: string;
|
|
299
|
+
includeArchived?: boolean;
|
|
300
|
+
}): Promise<LinkedRecordsResult>;
|
|
301
|
+
export declare function migrateLegacyIntakeItemsToDxcompleteTickets(db: Db): Promise<{
|
|
302
|
+
copied: number;
|
|
303
|
+
skipped: number;
|
|
304
|
+
}>;
|
|
305
|
+
export declare function createDxcompleteTicket(db: Db, input: CreateDxcompleteTicketInput, actor: ActorContext): Promise<DxcRecord>;
|
|
306
|
+
export declare function getDxcompleteTicket(db: Db, id: string, actor: ActorContext): Promise<DxcRecord>;
|
|
307
|
+
export declare function listDxcompleteTickets(db: Db, actor: ActorContext, limit: number, options?: {
|
|
308
|
+
includeArchived?: boolean;
|
|
309
|
+
}): Promise<DxcRecord[]>;
|
|
310
|
+
export declare function appendDxcompleteTicket(db: Db, input: AppendDxcompleteTicketInput, actor: ActorContext): Promise<DxcRecord>;
|
|
311
|
+
export declare function appendDxcompleteTicketReply(db: Db, input: AppendDxcompleteTicketReplyInput, actorId?: string): Promise<DxcRecord>;
|
|
312
|
+
export declare function appendJournalNote(db: Db, input: AppendJournalNoteInput, actorId: string): Promise<DxcRecord>;
|
|
313
|
+
export declare function readJournal(db: Db, input: ReadJournalInput): Promise<ReadJournalResult>;
|
|
314
|
+
export declare function getJournalEntry(db: Db, input: GetJournalEntryInput): Promise<DxcRecord>;
|
|
315
|
+
export declare function appendJournalSummary(db: Db, input: AppendJournalSummaryInput, actorId: string): Promise<DxcRecord>;
|
|
316
|
+
export declare function appendReviewNote(db: Db, input: AppendReviewNoteInput, actorId: string): Promise<DxcRecord>;
|
|
317
|
+
export declare function appendChangeEvent(db: Db, input: AppendChangeEventInput, actorId: string): Promise<DxcRecord>;
|
|
318
|
+
export declare function appendDeferralEvent(db: Db, input: AppendDeferralEventInput, actorId: string): Promise<DxcRecord>;
|
|
319
|
+
export declare function appendDecisionEntry(db: Db, input: AppendDecisionEntryInput, actorId: string): Promise<DxcRecord>;
|
|
320
|
+
export declare function appendTaskEntry(db: Db, input: AppendTaskEntryInput, actorId: string): Promise<DxcRecord>;
|
|
321
|
+
export declare function decisionEntryToCurrentDecision(entry: DecisionEntry): Record<string, unknown>;
|
|
322
|
+
export declare function taskEntryToCurrentStatus(entry: TaskEntry): Record<string, unknown>;
|
|
323
|
+
export declare function listUnreadDxcompleteTicketReplies(db: Db, actor: ActorContext, limit: number): Promise<DxcompleteTicketUnreadReplyResult[]>;
|
|
324
|
+
export declare function readDxcompleteTicket(db: Db, input: ReadDxcompleteTicketInput, actor: ActorContext): Promise<DxcRecord>;
|
|
325
|
+
export declare function archiveDxcompleteTicket(db: Db, input: ArchiveDxcompleteTicketInput, actor: ActorContext): Promise<DxcRecord>;
|
|
326
|
+
export declare function updateRecord(db: Db, input: UpdateRecordInput, actorId: string): Promise<DxcRecord>;
|
|
327
|
+
export declare function archiveRecord(db: Db, input: ArchiveRecordInput, actorId: string): Promise<DxcRecord>;
|
|
328
|
+
export declare function linkRecords(db: Db, input: {
|
|
329
|
+
fromType: CollectionName;
|
|
330
|
+
fromId: string;
|
|
331
|
+
toType: CollectionName;
|
|
332
|
+
toId: string;
|
|
333
|
+
workspaceId?: string;
|
|
334
|
+
relationship?: string;
|
|
335
|
+
}, actorId: string): Promise<DxcRecord>;
|
|
336
|
+
export declare function unlinkRecords(db: Db, input: UnlinkRecordsInput, actorId: string): Promise<DxcRecord>;
|