dxcomplete 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/.env.example +0 -7
  2. package/README.md +68 -103
  3. package/dist/cli.js +2 -24
  4. package/dist/validate.js +10 -26
  5. package/docs/cost-model.md +2 -2
  6. package/docs/decision-basis.md +5 -11
  7. package/docs/diagrams.md +3 -3
  8. package/docs/index.md +25 -39
  9. package/docs/model.md +15 -23
  10. package/docs/open-questions.md +1 -1
  11. package/docs/taxonomy.md +7 -8
  12. package/docs/workflows.md +3 -3
  13. package/package.json +24 -24
  14. package/templates/process/README.md +11 -11
  15. package/templates/process/controls.yml +19 -19
  16. package/templates/process/cost-model.yml +3 -3
  17. package/templates/process/decision-basis.yml +4 -4
  18. package/templates/process/diagrams/00-decision-basis.mmd +1 -1
  19. package/templates/process/diagrams/00-overview.mmd +1 -1
  20. package/templates/process/diagrams/01-intake-triage.mmd +4 -4
  21. package/templates/process/diagrams/02-product-definition.mmd +3 -3
  22. package/templates/process/diagrams/03-engineering-execution.mmd +1 -1
  23. package/templates/process/diagrams/04-qa-verification.mmd +1 -1
  24. package/templates/process/diagrams/05-product-validation.mmd +1 -1
  25. package/templates/process/diagrams/06-change-release-control.mmd +1 -1
  26. package/templates/process/diagrams/07-deployment-operations.mmd +1 -1
  27. package/templates/process/diagrams/08-support-incident-management.mmd +1 -1
  28. package/templates/process/diagrams/09-problem-improvement.mmd +1 -1
  29. package/templates/process/diagrams/10-risk-control-management.mmd +1 -1
  30. package/templates/process/diagrams/11-audit-evidence-capture.mmd +1 -1
  31. package/templates/process/roles.yml +6 -6
  32. package/templates/process/taxonomy.yml +46 -46
  33. package/templates/process/workflows.yml +29 -29
  34. package/website/account.html +57 -0
  35. package/website/app.js +177 -0
  36. package/website/flow.html +4 -0
  37. package/website/glossary.html +4 -0
  38. package/website/index.html +4 -0
  39. package/website/objects.html +4 -0
  40. package/website/operating-guide.html +4 -0
  41. package/website/outcomes.html +4 -0
  42. package/website/phase-build.html +4 -0
  43. package/website/phase-elicit.html +4 -0
  44. package/website/phase-go-live.html +4 -0
  45. package/website/phase-measure.html +4 -0
  46. package/website/phase-operate.html +4 -0
  47. package/website/phase-orient.html +4 -0
  48. package/website/phase-weigh.html +4 -0
  49. package/website/roles.html +4 -0
  50. package/website/styles.css +217 -1
  51. package/dist/http/service.d.ts +0 -7
  52. package/dist/http/service.js +0 -725
  53. package/dist/mcp/docs.d.ts +0 -114
  54. package/dist/mcp/docs.js +0 -626
  55. package/dist/mcp/server.d.ts +0 -20
  56. package/dist/mcp/server.js +0 -3059
  57. package/dist/runtime/auth.d.ts +0 -162
  58. package/dist/runtime/auth.js +0 -394
  59. package/dist/runtime/check.d.ts +0 -7
  60. package/dist/runtime/check.js +0 -16
  61. package/dist/runtime/config.d.ts +0 -17
  62. package/dist/runtime/config.js +0 -93
  63. package/dist/runtime/mongo.d.ts +0 -9
  64. package/dist/runtime/mongo.js +0 -56
  65. package/dist/runtime/records.d.ts +0 -427
  66. package/dist/runtime/records.js +0 -2092
  67. package/scripts/check-env-surface.mjs +0 -136
  68. package/scripts/check-public-copy.mjs +0 -263
  69. package/scripts/check-service-boundary.mjs +0 -63
  70. package/scripts/runtime-work-order.mjs +0 -506
  71. package/scripts/smoke-mcp-http.mjs +0 -4026
  72. package/src/cli.ts +0 -268
  73. package/src/http/server.ts +0 -314
  74. package/src/http/service.ts +0 -934
  75. package/src/init.ts +0 -262
  76. package/src/install-manifest.ts +0 -144
  77. package/src/mcp/docs.ts +0 -777
  78. package/src/mcp/server.ts +0 -4580
  79. package/src/package-root.ts +0 -31
  80. package/src/runtime/actor.ts +0 -61
  81. package/src/runtime/auth.ts +0 -673
  82. package/src/runtime/check.ts +0 -18
  83. package/src/runtime/config.ts +0 -128
  84. package/src/runtime/mongo.ts +0 -89
  85. package/src/runtime/records.ts +0 -3205
  86. package/src/runtime/workspace.ts +0 -155
  87. package/src/upgrade.ts +0 -356
  88. package/src/validate.ts +0 -141
  89. package/src/version.ts +0 -16
@@ -1,128 +0,0 @@
1
- import { constants as fsConstants } from "node:fs";
2
- import { access, readFile } from "node:fs/promises";
3
- import path from "node:path";
4
-
5
- export type RuntimeOptions = {
6
- cwd?: string;
7
- env?: NodeJS.ProcessEnv;
8
- envFile?: string;
9
- };
10
-
11
- export type RuntimeConfig = {
12
- mongodbUri: string;
13
- databaseName: string;
14
- googleClientId?: string;
15
- googleClientSecret?: string;
16
- serviceProvisioningSecret?: string;
17
- envFilePath?: string;
18
- };
19
-
20
- export class RuntimeConfigError extends Error {
21
- constructor(message: string) {
22
- super(message);
23
- this.name = "RuntimeConfigError";
24
- }
25
- }
26
-
27
- const DEFAULT_ENV_FILE = ".env.local";
28
- const DEFAULT_DATABASE_NAME = "dxcomplete";
29
-
30
- export async function loadRuntimeConfig(options: RuntimeOptions = {}): Promise<RuntimeConfig> {
31
- const cwd = path.resolve(options.cwd ?? process.cwd());
32
- const envFilePath = await resolveEnvFile(cwd, options.envFile);
33
- const fileEnv = envFilePath ? await parseEnvFile(envFilePath) : {};
34
- const env = {
35
- ...fileEnv,
36
- ...(options.env ?? process.env)
37
- };
38
-
39
- const mongodbUri = readRequiredEnv(env, "DXC_MONGODB_URI");
40
- const databaseName = readOptionalEnv(env, "DXC_DATABASE_NAME") ?? DEFAULT_DATABASE_NAME;
41
- const googleClientId = readOptionalEnv(env, "DXC_GOOGLE_CLIENT_ID");
42
- const googleClientSecret = readOptionalEnv(env, "DXC_GOOGLE_CLIENT_SECRET");
43
- const serviceProvisioningSecret = readOptionalEnv(env, "DXC_SERVICE_PROVISIONING_SECRET");
44
-
45
- return {
46
- mongodbUri,
47
- databaseName,
48
- ...(googleClientId ? { googleClientId } : {}),
49
- ...(googleClientSecret ? { googleClientSecret } : {}),
50
- ...(serviceProvisioningSecret ? { serviceProvisioningSecret } : {}),
51
- envFilePath
52
- };
53
- }
54
-
55
- async function resolveEnvFile(cwd: string, envFile?: string): Promise<string | undefined> {
56
- if (envFile) {
57
- const explicitPath = path.resolve(cwd, envFile);
58
- if (!(await fileExists(explicitPath))) {
59
- throw new RuntimeConfigError(`Env file not found: ${explicitPath}`);
60
- }
61
- return explicitPath;
62
- }
63
-
64
- const defaultPath = path.join(cwd, DEFAULT_ENV_FILE);
65
- return (await fileExists(defaultPath)) ? defaultPath : undefined;
66
- }
67
-
68
- async function parseEnvFile(filePath: string): Promise<NodeJS.ProcessEnv> {
69
- const content = await readFile(filePath, "utf8");
70
- const parsed: NodeJS.ProcessEnv = {};
71
-
72
- for (const [index, rawLine] of content.split(/\r?\n/).entries()) {
73
- const trimmed = rawLine.trim();
74
- if (!trimmed || trimmed.startsWith("#")) {
75
- continue;
76
- }
77
-
78
- const line = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed;
79
- const equalsIndex = line.indexOf("=");
80
- if (equalsIndex === -1) {
81
- throw new RuntimeConfigError(`Invalid env line ${index + 1} in ${filePath}. Expected KEY=value.`);
82
- }
83
-
84
- const key = line.slice(0, equalsIndex).trim();
85
- const value = line.slice(equalsIndex + 1).trim();
86
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
87
- throw new RuntimeConfigError(`Invalid env key "${key}" on line ${index + 1} in ${filePath}.`);
88
- }
89
-
90
- parsed[key] = unquote(value);
91
- }
92
-
93
- return parsed;
94
- }
95
-
96
- function readRequiredEnv(env: NodeJS.ProcessEnv, key: string): string {
97
- const value = readOptionalEnv(env, key);
98
- if (!value) {
99
- throw new RuntimeConfigError(
100
- `${key} is required. Create .env.local from .env.example or export ${key} before running this command.`
101
- );
102
- }
103
- return value;
104
- }
105
-
106
- function readOptionalEnv(env: NodeJS.ProcessEnv, key: string): string | undefined {
107
- const value = env[key]?.trim();
108
- return value ? value : undefined;
109
- }
110
-
111
- function unquote(value: string): string {
112
- if (
113
- (value.startsWith("\"") && value.endsWith("\"")) ||
114
- (value.startsWith("'") && value.endsWith("'"))
115
- ) {
116
- return value.slice(1, -1);
117
- }
118
- return value;
119
- }
120
-
121
- async function fileExists(filePath: string): Promise<boolean> {
122
- try {
123
- await access(filePath, fsConstants.F_OK);
124
- return true;
125
- } catch {
126
- return false;
127
- }
128
- }
@@ -1,89 +0,0 @@
1
- import { MongoClient, type Db } from "mongodb";
2
- import {
3
- OAUTH_AUTH_REQUESTS_COLLECTION,
4
- OAUTH_CLIENTS_COLLECTION,
5
- OAUTH_CODES_COLLECTION,
6
- OAUTH_TOKENS_COLLECTION,
7
- WORKSPACE_SERVICE_CLIENTS_COLLECTION,
8
- WORKSPACE_MEMBERSHIPS_COLLECTION
9
- } from "./auth.js";
10
- import { loadRuntimeConfig, type RuntimeConfig, type RuntimeOptions } from "./config.js";
11
- import {
12
- DXCOMPLETE_TICKET_COLLECTION_NAME,
13
- INDEX_COLLECTION_NAMES,
14
- READABLE_ID_COLLECTION_NAMES,
15
- READABLE_ID_SEQUENCES_COLLECTION,
16
- migrateLegacyIntakeItemsToDxcompleteTickets
17
- } from "./records.js";
18
-
19
- export type DxRuntime = {
20
- config: RuntimeConfig;
21
- client: MongoClient;
22
- db: Db;
23
- close: () => Promise<void>;
24
- };
25
-
26
- export async function connectRuntime(options: RuntimeOptions = {}): Promise<DxRuntime> {
27
- const config = await loadRuntimeConfig(options);
28
- const client = new MongoClient(config.mongodbUri, {
29
- serverSelectionTimeoutMS: 10000
30
- });
31
-
32
- await client.connect();
33
- const db = client.db(config.databaseName);
34
- await db.command({ ping: 1 });
35
- await migrateLegacyIntakeItemsToDxcompleteTickets(db);
36
- await ensureIndexes(db);
37
-
38
- return {
39
- config,
40
- client,
41
- db,
42
- close: () => client.close()
43
- };
44
- }
45
-
46
- async function ensureIndexes(db: Db): Promise<void> {
47
- await Promise.all(
48
- INDEX_COLLECTION_NAMES.map(async (collectionName) => {
49
- const collection = db.collection(collectionName);
50
- await collection.createIndex({ recordType: 1, createdAt: -1 });
51
- await collection.createIndex({ workspaceId: 1, recordType: 1, createdAt: -1 });
52
- await collection.createIndex({ "links.toId": 1 });
53
- await collection.createIndex({ workspaceId: 1, "links.toId": 1 });
54
-
55
- if ((READABLE_ID_COLLECTION_NAMES as readonly string[]).includes(collectionName)) {
56
- await collection.createIndex(
57
- { workspaceId: 1, readableId: 1 },
58
- {
59
- unique: true,
60
- partialFilterExpression: { readableId: { $exists: true } }
61
- }
62
- );
63
- }
64
-
65
- if (collectionName === DXCOMPLETE_TICKET_COLLECTION_NAME) {
66
- await collection.createIndex({ "fields.ownerActorId": 1, archivedAt: 1, updatedAt: -1 });
67
- await collection.createIndex({ "fields.entries.addressedToActorId": 1, "fields.entries.readAt": 1 });
68
- }
69
-
70
- if (collectionName === "journal_entries") {
71
- await collection.createIndex({ workspaceId: 1, "fields.kind": 1, archivedAt: 1, createdAt: 1 });
72
- await collection.createIndex({ workspaceId: 1, archivedAt: 1, createdAt: 1 });
73
- }
74
- })
75
- );
76
-
77
- await Promise.all([
78
- db.collection(WORKSPACE_MEMBERSHIPS_COLLECTION).createIndex({ workspaceId: 1, email: 1 }, { unique: true }),
79
- db.collection(WORKSPACE_MEMBERSHIPS_COLLECTION).createIndex({ provider: 1, providerSubject: 1 }),
80
- db.collection(WORKSPACE_SERVICE_CLIENTS_COLLECTION).createIndex({ workspaceId: 1, clientId: 1 }, { unique: true }),
81
- db.collection(WORKSPACE_SERVICE_CLIENTS_COLLECTION).createIndex({ clientId: 1 }, { unique: true }),
82
- db.collection(OAUTH_CLIENTS_COLLECTION).createIndex({ clientId: 1 }, { unique: true }),
83
- db.collection(OAUTH_AUTH_REQUESTS_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
84
- db.collection(OAUTH_CODES_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
85
- db.collection(OAUTH_TOKENS_COLLECTION).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
86
- db.collection(OAUTH_TOKENS_COLLECTION).createIndex({ workspaceId: 1, "actor.actorId": 1 }),
87
- db.collection(READABLE_ID_SEQUENCES_COLLECTION).createIndex({ workspaceId: 1, recordType: 1 }, { unique: true })
88
- ]);
89
- }