@haposoft/cafekit 0.16.0-rc.1 → 0.16.0-rc.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haposoft/cafekit",
|
|
3
|
-
"version": "0.16.0-rc.
|
|
3
|
+
"version": "0.16.0-rc.2",
|
|
4
4
|
"description": "Native spec-driven workflows for Claude Code, Codex CLI, and OpenCode. Bundles CafeKit skills, runtime hooks, agents, and installer scaffolding.",
|
|
5
5
|
"author": "Haposoft <nghialt@haposoft.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,12 +44,17 @@ Before reading any specific logic, you MUST run a Dependency Scope Check (Blast
|
|
|
44
44
|
|
|
45
45
|
| # | Pillar | Example Issues |
|
|
46
46
|
|---|--------|----------------|
|
|
47
|
-
| 1 | **Security** | XSS, SQL injection, hardcoded secrets, missing auth checks |
|
|
47
|
+
| 1 | **Security** | XSS, SQL injection, hardcoded secrets, missing auth checks, over-broad log redaction corrupting safe identifiers/public URLs, quote/delimiter-unsafe authorization redaction, non-idempotent redaction, filesystem write escaping via traversal/symlink/sibling-prefix, non-canonical return path, non-atomic write or leaked temp file |
|
|
48
48
|
| 2 | **Logic Correctness** | Race conditions, null references, off-by-one, unawait-ed async |
|
|
49
49
|
| 3 | **Architecture** | Cross-module coupling, layer separation violations, circular dependencies |
|
|
50
50
|
| 4 | **Principles (YAGNI/KISS/DRY)** | Code duplication, over-engineering, features outside scope |
|
|
51
51
|
| 5 | **Convention & Style** | Non-standard naming, missing type annotations, formatting issues |
|
|
52
52
|
|
|
53
|
+
### Critical-only invariants (enforce only when the diff touches these surfaces)
|
|
54
|
+
|
|
55
|
+
- **Logging redaction:** exact token-boundary matching (safe suffixes `_file`/`_path`/`_hint`/`_label` and `tokenizer` must not be redacted), public URLs unchanged unless they carry a credential, `Bearer`/`Basic` redaction preserves surrounding quotes and trailing `,`/`;`/whitespace outside the value, never drops the closing quote, and `redact(redact(x)) === redact(x)`.
|
|
56
|
+
- **Filesystem write boundary:** existing real directory root, reject empty/whitespace-only/URI/absolute/traversal/sibling-prefix before mutation, dual containment (lexical `path.resolve` **and** `realpath` of deepest existing parent), never follow or overwrite final symlink, never create parents outside root, atomic same-directory temp + `rename` with cleanup, return canonical `realpath` on success.
|
|
57
|
+
|
|
53
58
|
## Review Process
|
|
54
59
|
|
|
55
60
|
Assume the code may be AI-generated. Do not trust polished structure, confident comments, or happy-path tests — verify behavior from evidence.
|
|
@@ -144,6 +149,8 @@ When called from `develop` Step 4 (Quality Gate Auto-Fix):
|
|
|
144
149
|
- Cross-service behavior "proven" only by process-local memory, fake adapters, or other non-shared placeholders
|
|
145
150
|
- Files or features from later tasks delivered early without explicit scope-escape justification
|
|
146
151
|
- Task marked complete while required commands/evidence are still FAIL / UNVERIFIED
|
|
152
|
+
- Logging redaction that over-redacts safe identifiers/public URLs, drops closing quotes, consumes `,`/`;` delimiters, or is not idempotent when the diff touches redaction/sanitization
|
|
153
|
+
- Filesystem write that returns a lexical path instead of canonical `realpath`, skips `realpath` parent containment, follows or overwrites a final symlink, creates or mutates anything outside the root on rejection, or leaks a temp file / misses atomic same-directory `rename`
|
|
147
154
|
|
|
148
155
|
## Operating Guidelines
|
|
149
156
|
|
|
@@ -257,6 +257,58 @@ const dbPassword = process.env.DB_PASSWORD;
|
|
|
257
257
|
if (!dbPassword) throw new Error('DB_PASSWORD not set');
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
+
## Critical Security Invariants (apply only when the task touches these surfaces)
|
|
261
|
+
|
|
262
|
+
These invariants are lane-aware: enforce them for Critical tasks that touch the
|
|
263
|
+
named surface; for Direct/Standard tasks that happen to touch it, apply the same
|
|
264
|
+
checks with proportional evidence (targeted unit test + diff self-check for Direct,
|
|
265
|
+
bounded suite for Standard). Do not impose a fixed heavy ceremony on every task.
|
|
266
|
+
|
|
267
|
+
### Logging & Secret Redaction
|
|
268
|
+
|
|
269
|
+
- Match secret names by exact token boundaries, not broad substrings. Never redact
|
|
270
|
+
by substring inside safe identifiers — e.g. names ending in `_file`, `_path`,
|
|
271
|
+
`_hint`, `_label` or containing `tokenizer` must stay intact. Preserve the
|
|
272
|
+
field/key name, replace only the value with `[REDACTED]` (use `[REDACTED-PEM]`
|
|
273
|
+
for PEM blocks, keeping the surrounding structure).
|
|
274
|
+
- Leave public URLs and credential-free strings untouched. URL redaction applies
|
|
275
|
+
only when a credential is present in the URL (e.g. `user:pass@host`).
|
|
276
|
+
- Authorization redaction is quote-aware and delimiter-safe: match schemes
|
|
277
|
+
`Bearer`/`Basic` case-insensitively, redact only the credential that follows,
|
|
278
|
+
preserve surrounding quotes and trailing delimiters (`,`, `;`, whitespace) outside
|
|
279
|
+
the redacted value, and never drop the closing quote.
|
|
280
|
+
- Idempotence: `redact(redact(x)) === redact(x)`. The markers `[REDACTED]` /
|
|
281
|
+
`[REDACTED-PEM]` are stable and not re-wrapped or corrupted.
|
|
282
|
+
- Verification guidance: cover true-positive credential cases, false-positive
|
|
283
|
+
safe-identifier and public-URL cases, quoted `Bearer`/`Basic` with trailing
|
|
284
|
+
delimiters, multi-line/PEM cases when relevant, and an idempotence round-trip.
|
|
285
|
+
Assert that no secret appears in error messages or completion reports and that
|
|
286
|
+
safe values are byte-identical after redaction.
|
|
287
|
+
|
|
288
|
+
### Filesystem Write Boundary
|
|
289
|
+
|
|
290
|
+
- Require an existing real directory as root. Reject before any mutation when
|
|
291
|
+
`targetPath` is empty or whitespace-only, contains a URI scheme, is absolute,
|
|
292
|
+
escapes via `..` segments, or escapes via sibling-prefix (`root` vs
|
|
293
|
+
`root-evil`).
|
|
294
|
+
- Containment needs two checks: lexical containment of the resolved path
|
|
295
|
+
(`path.resolve(root, target)` inside root) **and** `realpath` containment of
|
|
296
|
+
the deepest existing parent directory. This blocks symlink-pointing-outside
|
|
297
|
+
and traversal that lexical check alone would miss. Never follow or overwrite a
|
|
298
|
+
symlink at the final target; never create parent directories outside root.
|
|
299
|
+
- Perform atomic same-directory write: create a temporary file in the target
|
|
300
|
+
directory, write fully, then `rename` into place. Remove the temp file on any
|
|
301
|
+
error. Rejections must happen before creating or modifying anything outside root.
|
|
302
|
+
- Return the canonical `realpath` of the target on success (e.g. macOS
|
|
303
|
+
`/var` → `/private/var` alias must resolve). Keep the public API otherwise
|
|
304
|
+
unchanged.
|
|
305
|
+
- Verification guidance: nested success, traversal / absolute / URI / sibling-prefix
|
|
306
|
+
rejection, parent-symlink rejection, final-symlink rejection (do not follow or
|
|
307
|
+
overwrite), no-outside-mutation assertion (filesystem outside root unchanged on
|
|
308
|
+
failure), atomic temp cleanup, and canonical return-path equality. Critical runs
|
|
309
|
+
the full project suite; Direct/Standard use proportional lane evidence (targeted
|
|
310
|
+
unit test + diff self-check for Direct, bounded suite for Standard).
|
|
311
|
+
|
|
260
312
|
## API Security Checklist
|
|
261
313
|
|
|
262
314
|
- [ ] Use HTTPS/TLS 1.3 only
|
|
@@ -45,6 +45,26 @@ Stage A applies same spec compliance review checklist for every tier: scope, req
|
|
|
45
45
|
- Scope fidelity is mandatory: missing scoped behavior, extra unapproved behavior, or task output that exists only as orphaned/unreachable code is a review failure even when build/tests pass.
|
|
46
46
|
- Runtime-facing artifacts must be reachable from the real entrypoint/caller named by the task or the task-aware scout report.
|
|
47
47
|
|
|
48
|
+
### Critical security verification (apply only when the task touches these surfaces)
|
|
49
|
+
|
|
50
|
+
No fixed ceremony for every task — apply the checklist below only when the
|
|
51
|
+
touched files, risk signals, or task description include logging/redaction or
|
|
52
|
+
filesystem write boundaries. Direct uses targeted unit test + diff self-check,
|
|
53
|
+
Standard a bounded suite, Critical strict evidence (inspector/test-runner/
|
|
54
|
+
code-auditor per lane policy).
|
|
55
|
+
|
|
56
|
+
- **Logging / secret redaction:** assert broad matchers did not corrupt safe
|
|
57
|
+
identifiers or public URLs; quoted `Bearer`/`Basic` redaction keeps surrounding
|
|
58
|
+
quotes and leaves trailing `,`/`;`/whitespace outside the replacement; redaction
|
|
59
|
+
is idempotent (`redact(redact(x)) === redact(x)`); no secret appears in test
|
|
60
|
+
failures or the verification receipt.
|
|
61
|
+
- **Filesystem write boundary:** assert lexical `path.resolve` **and** `realpath` of
|
|
62
|
+
the deepest existing parent both stay inside the canonical root; parent-symlink
|
|
63
|
+
and final-symlink targets are rejected without following/overwriting; no file
|
|
64
|
+
outside root is created or mutated on rejection; write goes via same-directory
|
|
65
|
+
temp file + atomic `rename` with cleanup on error; success returns canonical
|
|
66
|
+
`realpath` (platform aliases resolved).
|
|
67
|
+
|
|
48
68
|
## Flash Gate (`--flash`)
|
|
49
69
|
|
|
50
70
|
Use this only when `/hapo:develop ... --flash` is present.
|