specky-sdd 3.4.0 → 3.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"tool-enforcement.d.ts","sourceRoot":"","sources":["../../src/tools/tool-enforcement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAiB,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AASjE,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,IAAI,CAAC;CACf;AA+BD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIhD;AAqJD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CASN"}
1
+ {"version":3,"file":"tool-enforcement.d.ts","sourceRoot":"","sources":["../../src/tools/tool-enforcement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,QAAQ,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AASjE,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,IAAI,CAAC;CACf;AAWD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAuBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIhD;AAwBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,CAajE;AAqLD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CASN"}
@@ -37,11 +37,40 @@ function getToolInput(args) {
37
37
  const firstArg = args[0];
38
38
  return isRecord(firstArg) ? firstArg : {};
39
39
  }
40
- function getActiveRole(rbacEngine) {
40
+ function isRbacRole(value) {
41
+ return value === "viewer" || value === "contributor" || value === "admin";
42
+ }
43
+ /**
44
+ * Extract the authenticated identity from the MCP request extra (second
45
+ * handler argument). The HTTP transport propagates `req.auth` as
46
+ * `extra.authInfo`; the principal/role live in `authInfo.extra`.
47
+ */
48
+ export function getCallerIdentity(args) {
49
+ const extra = args[1];
50
+ if (!isRecord(extra) || !isRecord(extra["authInfo"]))
51
+ return {};
52
+ const authInfo = extra["authInfo"];
53
+ const authExtra = isRecord(authInfo["extra"]) ? authInfo["extra"] : {};
54
+ const principal = typeof authExtra["principal"] === "string" && authExtra["principal"]
55
+ ? authExtra["principal"]
56
+ : typeof authInfo["clientId"] === "string" && authInfo["clientId"]
57
+ ? authInfo["clientId"]
58
+ : undefined;
59
+ const role = isRbacRole(authExtra["role"]) ? authExtra["role"] : undefined;
60
+ return { principal, role };
61
+ }
62
+ /**
63
+ * Role precedence: authenticated identity (token table) > SDD_ROLE env
64
+ * (local/stdio convenience — the launcher owns the process anyway) > config
65
+ * default_role. When a request carries an authenticated identity, the env var
66
+ * is deliberately ignored: a remote caller must not out-vote its token.
67
+ */
68
+ function getActiveRole(rbacEngine, identity) {
69
+ if (identity.role)
70
+ return identity.role;
41
71
  const envRole = process.env["SDD_ROLE"];
42
- if (envRole === "viewer" || envRole === "contributor" || envRole === "admin") {
72
+ if (isRbacRole(envRole))
43
73
  return envRole;
44
- }
45
74
  return rbacEngine.roleDefault;
46
75
  }
47
76
  function buildDeniedResponse(payload) {
@@ -58,6 +87,7 @@ async function auditStart(auditLogger, context, phase) {
58
87
  feature_number: context.featureNumber,
59
88
  phase,
60
89
  role: context.activeRole,
90
+ principal: context.principal,
61
91
  result: "success",
62
92
  summary: "Execution started",
63
93
  input_hash: context.inputHash,
@@ -72,6 +102,7 @@ async function auditSuccess(auditLogger, context, output, phase) {
72
102
  feature_number: context.featureNumber,
73
103
  phase,
74
104
  role: context.activeRole,
105
+ principal: context.principal,
75
106
  result: "success",
76
107
  summary: "Execution completed",
77
108
  input_hash: context.inputHash,
@@ -87,38 +118,56 @@ async function auditError(auditLogger, context, summary, phase) {
87
118
  feature_number: context.featureNumber,
88
119
  phase,
89
120
  role: context.activeRole,
121
+ principal: context.principal,
90
122
  result: "error",
91
123
  summary,
92
124
  input_hash: context.inputHash,
93
125
  previous_hash: auditLogger.currentHash,
94
126
  });
95
127
  }
128
+ /**
129
+ * Post-execution audit failures cannot un-run the tool; even in fail-closed
130
+ * mode the result is returned and the failure is surfaced on stderr. Only the
131
+ * pre-execution entry gates execution.
132
+ */
133
+ async function auditBestEffort(write, toolName) {
134
+ try {
135
+ await write;
136
+ }
137
+ catch (error) {
138
+ const message = error instanceof Error ? error.message : String(error);
139
+ console.error(`[specky] Post-execution audit write failed for ${toolName}: ${message}`);
140
+ }
141
+ }
96
142
  function wrapToolHandler(toolName, handler, options) {
97
143
  return async (...args) => {
98
144
  const input = getToolInput(args);
99
145
  const specDir = getSpecDir(input);
100
- const activeRole = getActiveRole(options.rbacEngine);
146
+ const identity = getCallerIdentity(args);
147
+ const activeRole = getActiveRole(options.rbacEngine, identity);
101
148
  const context = {
102
149
  toolName,
103
150
  specDir,
104
151
  featureNumber: getFeatureNumber(input),
105
152
  activeRole,
153
+ principal: identity.principal,
106
154
  inputHash: hashValue(input),
107
155
  };
108
156
  const rbac = options.rbacEngine.checkAccess(activeRole, toolName);
109
157
  if (!rbac.allowed) {
110
- await auditError(options.auditLogger, context, rbac.reason ?? "RBAC access denied");
158
+ await auditBestEffort(auditError(options.auditLogger, context, rbac.reason ?? "RBAC access denied"), toolName);
111
159
  return buildDeniedResponse({
112
160
  error: "access_denied",
113
161
  tool: toolName,
114
162
  active_role: activeRole,
163
+ ...(identity.principal ? { principal: identity.principal } : {}),
115
164
  message: rbac.reason ?? `Role ${activeRole} cannot invoke ${toolName}.`,
116
165
  });
117
166
  }
118
167
  const phaseCheck = await options.stateMachine.validatePhaseForTool(specDir, toolName);
119
168
  if (!phaseCheck.allowed) {
120
169
  const message = phaseCheck.error_message ?? `Tool ${toolName} is not allowed in phase ${phaseCheck.current_phase}.`;
121
- await auditError(options.auditLogger, context, message, phaseCheck.current_phase);
170
+ await auditBestEffort(auditError(options.auditLogger, context, message, phaseCheck.current_phase), toolName);
122
171
  return buildDeniedResponse({
123
172
  error: "phase_validation_failed",
124
173
  tool: toolName,
@@ -127,15 +176,27 @@ function wrapToolHandler(toolName, handler, options) {
127
176
  message,
128
177
  });
129
178
  }
130
- await auditStart(options.auditLogger, context, phaseCheck.current_phase);
179
+ // Fail-closed gate: if the pre-execution audit entry cannot be written,
180
+ // the tool does not run (no unaudited actions in enterprise mode).
181
+ try {
182
+ await auditStart(options.auditLogger, context, phaseCheck.current_phase);
183
+ }
184
+ catch (error) {
185
+ const message = error instanceof Error ? error.message : String(error);
186
+ return buildDeniedResponse({
187
+ error: "audit_unavailable",
188
+ tool: toolName,
189
+ message: `Refusing to execute: the audit trail could not be written and audit.fail_closed is on. (${message})`,
190
+ });
191
+ }
131
192
  try {
132
193
  const result = await handler(...args);
133
- await auditSuccess(options.auditLogger, context, result, phaseCheck.current_phase);
194
+ await auditBestEffort(auditSuccess(options.auditLogger, context, result, phaseCheck.current_phase), toolName);
134
195
  return result;
135
196
  }
136
197
  catch (error) {
137
198
  const message = error instanceof Error ? error.message : String(error);
138
- await auditError(options.auditLogger, context, message, phaseCheck.current_phase);
199
+ await auditBestEffort(auditError(options.auditLogger, context, message, phaseCheck.current_phase), toolName);
139
200
  throw error;
140
201
  }
141
202
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tool-enforcement.js","sourceRoot":"","sources":["../../src/tools/tool-enforcement.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-enforcement.js","sourceRoot":"","sources":["../../src/tools/tool-enforcement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import type { RbacRole } from "../services/rbac-engine.js";
3
+ declare const tokenEntrySchema: z.ZodObject<{
4
+ principal: z.ZodString;
5
+ role: z.ZodEnum<{
6
+ viewer: "viewer";
7
+ contributor: "contributor";
8
+ admin: "admin";
9
+ }>;
10
+ token: z.ZodOptional<z.ZodString>;
11
+ token_sha256: z.ZodOptional<z.ZodString>;
12
+ }, z.core.$strict>;
13
+ export type TokenTableEntry = z.infer<typeof tokenEntrySchema>;
14
+ export interface BearerIdentity {
15
+ authorized: boolean;
16
+ /** Set when the token table matched a named token. */
17
+ principal?: string;
18
+ /** Set when the token table matched a named token. */
19
+ role?: RbacRole;
20
+ }
21
+ /**
22
+ * Load and validate the tokens file. Throws on any problem — the caller must
23
+ * treat a configured-but-broken tokens file as fatal (fail-closed).
24
+ */
25
+ export declare function loadTokenTable(filePath: string): TokenTableEntry[];
26
+ export declare function sha256Hex(value: string): string;
27
+ /**
28
+ * Resolve the identity behind an Authorization header.
29
+ *
30
+ * - Token table configured → the presented token must match a named entry;
31
+ * returns its principal + role. The shared token is ignored in this mode
32
+ * (named identities only).
33
+ * - Only SDD_HTTP_TOKEN configured → legacy single shared token; authorized
34
+ * requests get principal "shared-token" and no role (RBAC falls back to
35
+ * SDD_ROLE / default_role).
36
+ * - Neither configured → authorized (auth disabled; loopback bind is the
37
+ * remaining guard).
38
+ */
39
+ export declare function resolveBearerIdentity(authorizationHeader: string | undefined, table: readonly TokenTableEntry[], sharedToken: string): BearerIdentity;
40
+ export {};
41
+ //# sourceMappingURL=token-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-table.d.ts","sourceRoot":"","sources":["../../src/utils/token-table.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAG3D,QAAA,MAAM,gBAAgB;;;;;;;;;kBAalB,CAAC;AAQL,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAYlE;AAQD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,mBAAmB,EAAE,MAAM,GAAG,SAAS,EACvC,KAAK,EAAE,SAAS,eAAe,EAAE,EACjC,WAAW,EAAE,MAAM,GAClB,cAAc,CAuBhB"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * token-table.ts — named bearer tokens for the HTTP transport.
3
+ *
4
+ * Enterprise deployments map each token to an authenticated principal and an
5
+ * RBAC role via a YAML file referenced by SDD_HTTP_TOKENS_FILE. The file must
6
+ * live OUTSIDE the workspace (e.g. /etc/specky/tokens.yml, mode 0600) — the
7
+ * whole point is that workspace writers cannot mint themselves a role.
8
+ *
9
+ * tokens:
10
+ * - principal: alice
11
+ * role: admin
12
+ * token_sha256: "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
13
+ * - principal: ci-bot
14
+ * role: viewer
15
+ * token: "plaintext-also-works" # sha256 form is recommended
16
+ *
17
+ * Loading is fail-closed: a configured file that is missing or malformed
18
+ * throws, so the server refuses to start with broken auth instead of silently
19
+ * accepting everyone.
20
+ */
21
+ import { readFileSync } from "node:fs";
22
+ import { createHash, timingSafeEqual } from "node:crypto";
23
+ import { parse } from "yaml";
24
+ import { z } from "zod";
25
+ import { isBearerAuthorized } from "./http-auth.js";
26
+ const tokenEntrySchema = z
27
+ .object({
28
+ principal: z.string().min(1),
29
+ role: z.enum(["viewer", "contributor", "admin"]),
30
+ token: z.string().min(8).optional(),
31
+ token_sha256: z
32
+ .string()
33
+ .regex(/^[0-9a-fA-F]{64}$/, "token_sha256 must be a 64-char hex SHA-256")
34
+ .optional(),
35
+ })
36
+ .strict()
37
+ .refine((e) => Boolean(e.token) !== Boolean(e.token_sha256), {
38
+ message: "each token entry needs exactly one of `token` or `token_sha256`",
39
+ });
40
+ const tokenTableSchema = z
41
+ .object({
42
+ tokens: z.array(tokenEntrySchema).min(1),
43
+ })
44
+ .strict();
45
+ /**
46
+ * Load and validate the tokens file. Throws on any problem — the caller must
47
+ * treat a configured-but-broken tokens file as fatal (fail-closed).
48
+ */
49
+ export function loadTokenTable(filePath) {
50
+ const raw = readFileSync(filePath, "utf-8");
51
+ const parsed = parse(raw) ?? {};
52
+ const result = tokenTableSchema.safeParse(parsed);
53
+ if (!result.success) {
54
+ throw new Error(`Invalid tokens file ${filePath}: ${result.error.issues
55
+ .map((i) => (i.path.length ? `${i.path.join(".")}: ${i.message}` : i.message))
56
+ .join("; ")}`);
57
+ }
58
+ return result.data.tokens;
59
+ }
60
+ function constantTimeEqual(a, b) {
61
+ const bufA = Buffer.from(a);
62
+ const bufB = Buffer.from(b);
63
+ return bufA.length === bufB.length && timingSafeEqual(bufA, bufB);
64
+ }
65
+ export function sha256Hex(value) {
66
+ return createHash("sha256").update(value).digest("hex");
67
+ }
68
+ /**
69
+ * Resolve the identity behind an Authorization header.
70
+ *
71
+ * - Token table configured → the presented token must match a named entry;
72
+ * returns its principal + role. The shared token is ignored in this mode
73
+ * (named identities only).
74
+ * - Only SDD_HTTP_TOKEN configured → legacy single shared token; authorized
75
+ * requests get principal "shared-token" and no role (RBAC falls back to
76
+ * SDD_ROLE / default_role).
77
+ * - Neither configured → authorized (auth disabled; loopback bind is the
78
+ * remaining guard).
79
+ */
80
+ export function resolveBearerIdentity(authorizationHeader, table, sharedToken) {
81
+ if (table.length === 0) {
82
+ return { authorized: isBearerAuthorized(authorizationHeader, sharedToken) };
83
+ }
84
+ const prefix = "Bearer ";
85
+ if (!authorizationHeader || !authorizationHeader.startsWith(prefix)) {
86
+ return { authorized: false };
87
+ }
88
+ const presented = authorizationHeader.slice(prefix.length);
89
+ const presentedSha = sha256Hex(presented);
90
+ // Evaluate every entry (no early exit) to keep timing independent of match position.
91
+ let matched;
92
+ for (const entry of table) {
93
+ const hit = entry.token_sha256
94
+ ? constantTimeEqual(presentedSha, entry.token_sha256.toLowerCase())
95
+ : constantTimeEqual(presented, entry.token ?? "");
96
+ if (hit && !matched)
97
+ matched = entry;
98
+ }
99
+ if (!matched)
100
+ return { authorized: false };
101
+ return { authorized: true, principal: matched.principal, role: matched.role };
102
+ }
103
+ //# sourceMappingURL=token-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-table.js","sourceRoot":"","sources":["../../src/utils/token-table.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specky-sdd",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "Specky — Spec-Driven Development CLI toolkit. 58 MCP tools, 13 agents, 22 prompts, 8 skills, 16 hooks. Unified `specky` CLI installs to Claude Code or GitHub Copilot on macOS, Linux, and Windows.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",