@cosmicdrift/kumiko-guards 0.367.0 → 0.368.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/README.md +2 -2
- package/package.json +2 -2
- package/src/_lib/sql-inventory.ts +2 -1
- package/src/guard-direct-entity-writes.ts +3 -3
- package/src/guard-no-date-api.ts +2 -5
- package/src/guard-raw-sql.ts +3 -3
- package/src/guard-section-fields-raw.ts +1 -1
- package/src/guard-table-ddl.ts +4 -2
- package/src/guard-test-stack-drift.ts +2 -0
package/README.md
CHANGED
|
@@ -46,13 +46,13 @@ merged on top. A security exception that expires within 14 days blocks.
|
|
|
46
46
|
## Raw-SQL markers
|
|
47
47
|
|
|
48
48
|
`guard-raw-sql` blocks `.unsafe()` / `asRawClient()` outside `db/queries/*`,
|
|
49
|
-
`
|
|
49
|
+
`db/query.ts` and testing code. A `// kumiko-lint-ignore raw-sql <reason>`
|
|
50
50
|
marker on the call's line or the line above only suppresses while its
|
|
51
51
|
(file, reason) pair is frozen in `.kumiko-raw-sql-baseline.json` at the repo
|
|
52
52
|
root. A new or reworded marker without a baseline entry fails the check, so
|
|
53
53
|
every exception shows up as a baseline diff in review. Without a baseline file
|
|
54
54
|
the guard only warns, so consumers do not break on bump. Prefer a typed
|
|
55
|
-
`
|
|
55
|
+
`db/query` helper; freeze a deliberate exception with:
|
|
56
56
|
|
|
57
57
|
```
|
|
58
58
|
bunx kumiko-guards checks --write-baseline --guard=guard-raw-sql
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-guards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.368.0",
|
|
4
4
|
"description": "AST-based security guards for Kumiko repos: direct-fs/fetch, tenant escalation, admin-API, escape hatches and related checks, run over a shared ts-morph project.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"kumiko-pre-push": "./src/pre-push.sh"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@cosmicdrift/kumiko-repo-manifest": "0.
|
|
31
|
+
"@cosmicdrift/kumiko-repo-manifest": "0.368.0",
|
|
32
32
|
"ts-morph": "^28.0.0"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
@@ -65,8 +65,9 @@ export const RAW_SQL_ALLOWLIST: ReadonlyArray<RegExp> = [
|
|
|
65
65
|
/(^|\/)(packages\/[^/]+\/)?src\/db\/migrate-runner\.ts$/,
|
|
66
66
|
/(^|\/)(packages\/[^/]+\/)?src\/db\/schema-inspection\.ts$/,
|
|
67
67
|
/(^|\/)(packages\/[^/]+\/)?src\/db\/render-ddl\.ts$/,
|
|
68
|
-
/(^|\/)(packages\/[^/]+\/)?src\/
|
|
68
|
+
/(^|\/)(packages\/[^/]+\/)?src\/db\/query\.ts$/,
|
|
69
69
|
/(^|\/)(packages\/[^/]+\/)?src\/testing\//,
|
|
70
|
+
/(^|\/)packages\/testing\/src\/helpers\//,
|
|
70
71
|
// ponytail: explicit enumeration — a blanket regex would auto-allow any new .unsafe()
|
|
71
72
|
/\/bundled-features\/src\/config\/db\/queries\/resolver\.ts$/,
|
|
72
73
|
/\/bundled-features\/src\/custom-fields\/db\/queries\/field-access\.ts$/,
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* 2. **Find direct writes.** Two forms:
|
|
23
23
|
* - Method form `<receiver>.insert(<tableIdent>)` / `.update` / `.delete`.
|
|
24
24
|
* - Function form `insertOne|updateMany|deleteMany|...(<db>, <tableIdent>,
|
|
25
|
-
* ...)` from `@cosmicdrift/kumiko-framework/
|
|
25
|
+
* ...)` from `@cosmicdrift/kumiko-framework/db` (table = arg[1]) —
|
|
26
26
|
* exactly the path that created the sessions-instance bug
|
|
27
27
|
* (`updateMany(ctx.db.raw, userSessionTable, ...)` without a
|
|
28
28
|
* lifecycle event).
|
|
@@ -81,7 +81,7 @@ const EXCLUDE =
|
|
|
81
81
|
// projection apply.
|
|
82
82
|
const TX_RECEIVER_NAMES = new Set(["tx", "trx", "handle"]);
|
|
83
83
|
|
|
84
|
-
//
|
|
84
|
+
// db/query function helpers with signature `(db, table, ...)` — table is
|
|
85
85
|
// always arg[1]. A direct write on an ES table goes through these just as
|
|
86
86
|
// often as through the Drizzle method form. Maps to the coarse op bucket
|
|
87
87
|
// for the violation message.
|
|
@@ -340,7 +340,7 @@ function isInsideProjectionApply(callNode: Node): boolean {
|
|
|
340
340
|
|
|
341
341
|
// Extracts (table identifier, db/receiver expression, op) from a write
|
|
342
342
|
// call — both forms: the Drizzle method `<recv>.insert(table)` and the
|
|
343
|
-
//
|
|
343
|
+
// db/query function `updateMany(db, table, ...)`. Casts around the table arg are
|
|
344
344
|
// unwrapped; undefined for non-writes or when the table arg is still no plain
|
|
345
345
|
// identifier (computed tables are not resolvable → skip, never a false block).
|
|
346
346
|
function resolveWrite(
|
package/src/guard-no-date-api.ts
CHANGED
|
@@ -53,9 +53,6 @@ const ALLOWLIST = [
|
|
|
53
53
|
// DB layer: drizzle column wrapper, migration tooling — Date is a
|
|
54
54
|
// primitive wire format there
|
|
55
55
|
/packages\/framework\/src\/db\//,
|
|
56
|
-
// Bun.SQL layer (post-Drizzle replacement) — same boundary as db/,
|
|
57
|
-
// converts Date→Temporal at the driver boundary.
|
|
58
|
-
/packages\/framework\/src\/bun-db\//,
|
|
59
56
|
// Event-store internals: createdAt stamps, snapshot time, archive time
|
|
60
57
|
/packages\/framework\/src\/event-store\//,
|
|
61
58
|
// Pipeline: system hooks, idempotency cache (low-level timestamps)
|
|
@@ -76,7 +73,7 @@ const ALLOWLIST = [
|
|
|
76
73
|
// it's defaults/audit stamps working together with the DB layer.
|
|
77
74
|
/packages\/framework\/src\/engine\/(types|registry|config-helpers|create-app|define-feature|state-machine|access|field-access|boot-validator|qualified-name)\.ts$/,
|
|
78
75
|
// Testing helpers
|
|
79
|
-
/packages\/
|
|
76
|
+
/packages\/testing\/src\/helpers\//,
|
|
80
77
|
// Search adapter internals
|
|
81
78
|
/packages\/framework\/src\/search\//,
|
|
82
79
|
// File storage (coming in Gap-04)
|
|
@@ -111,7 +108,7 @@ const ALLOWLIST = [
|
|
|
111
108
|
// Date object from fs.Stats.mtimeMs — wire boundary, not a Temporal format.
|
|
112
109
|
/packages\/server-runtime\/src\/run-prod-app-static-files\.ts$/,
|
|
113
110
|
// Bun.SQL timestamptz columns arrive as native Date (driver wire format,
|
|
114
|
-
// same reason as packages/framework/src/
|
|
111
|
+
// same reason as packages/framework/src/db/ above).
|
|
115
112
|
/packages\/publish\/src\/rollback\.ts$/,
|
|
116
113
|
];
|
|
117
114
|
|
package/src/guard-raw-sql.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* on the call's own line or the line directly above (one hit per marker). A bare tag with no
|
|
8
8
|
* reason text after it does NOT suppress the finding — production code
|
|
9
9
|
* should otherwise route SQL through `db/queries/*` or typed
|
|
10
|
-
* `
|
|
10
|
+
* `db/query` helpers.
|
|
11
11
|
*
|
|
12
12
|
* A marker only suppresses while its (file, reason) pair is frozen in
|
|
13
13
|
* `.kumiko-raw-sql-baseline.json` at the repo root, so every new or reworded
|
|
@@ -116,7 +116,7 @@ export async function collectRawSqlFindings(
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
const MARKER_REMEDIATION =
|
|
119
|
-
"New or reworded raw-sql marker. Use a typed
|
|
119
|
+
"New or reworded raw-sql marker. Use a typed db/query helper (selectMany, selectInnerJoin, " +
|
|
120
120
|
"insertOnConflictDoNothing, upsertOnConflict, aggregateWhere, where jsonText …) if one fits; " +
|
|
121
121
|
"otherwise freeze the exception with `kumiko-guards checks --write-baseline --guard=guard-raw-sql` " +
|
|
122
122
|
"so the baseline diff shows up in review.";
|
|
@@ -124,7 +124,7 @@ const MARKER_REMEDIATION =
|
|
|
124
124
|
export const check: RepoCheck = {
|
|
125
125
|
name: "guard-raw-sql",
|
|
126
126
|
hint:
|
|
127
|
-
"Rule: runtime SQL only in db/queries/*,
|
|
127
|
+
"Rule: runtime SQL only in db/queries/*, db/query.ts, testing/*, or with " +
|
|
128
128
|
"// kumiko-lint-ignore raw-sql <reason> on the line or the line above — and that " +
|
|
129
129
|
"(file, reason) must be frozen in .kumiko-raw-sql-baseline.json " +
|
|
130
130
|
"(`kumiko-guards checks --write-baseline --guard=guard-raw-sql`).",
|
|
@@ -67,7 +67,7 @@ const SCAN: ScanSpec = {
|
|
|
67
67
|
frameworkWithin: [
|
|
68
68
|
"packages/framework/src/engine/**",
|
|
69
69
|
"packages/framework/src/i18n/**",
|
|
70
|
-
"packages/
|
|
70
|
+
"packages/testing/src/helpers/**",
|
|
71
71
|
"packages/headless/src/**",
|
|
72
72
|
"packages/renderer/src/app/**",
|
|
73
73
|
],
|
package/src/guard-table-ddl.ts
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
* - packages/framework/src/event-store/** ES meta tables
|
|
18
18
|
* - packages/framework/src/pipeline/event-consumer-state.ts
|
|
19
19
|
* - packages/framework/src/pipeline/projection-state.ts
|
|
20
|
-
* - packages/framework/src/
|
|
20
|
+
* - packages/framework/src/db/table-push.ts the DDL helpers themselves
|
|
21
|
+
* - packages/testing/src/stack/** test-stack helpers, pushEntityProjectionTables, helper definitions
|
|
21
22
|
* - **\/__tests__/** test setup
|
|
22
23
|
* - **\/drizzle/** drizzle-kit configuration
|
|
23
24
|
* - **\/bin/migrate.ts app-owned migrate CLI
|
|
@@ -45,7 +46,8 @@ export const ALLOWLIST_PATTERNS: ReadonlyArray<RegExp> = [
|
|
|
45
46
|
/\/packages\/framework\/src\/event-store\//,
|
|
46
47
|
/\/packages\/framework\/src\/pipeline\/event-consumer-state\.ts$/,
|
|
47
48
|
/\/packages\/framework\/src\/pipeline\/projection-state\.ts$/,
|
|
48
|
-
/\/packages\/framework\/src\/
|
|
49
|
+
/\/packages\/framework\/src\/db\/table-push\.ts$/,
|
|
50
|
+
/\/packages\/testing\/src\/stack\//,
|
|
49
51
|
/\/__tests__\//,
|
|
50
52
|
/\/drizzle\//,
|
|
51
53
|
/\/bin\/migrate\.ts$/,
|
|
@@ -41,6 +41,8 @@ const SCAN: ScanSpec = {
|
|
|
41
41
|
"packages/framework/src/**/*.integration.test.ts",
|
|
42
42
|
"packages/bundled-features/src/**/*.integration.ts",
|
|
43
43
|
"packages/bundled-features/src/**/*.integration.test.ts",
|
|
44
|
+
"packages/testing/src/**/*.integration.ts",
|
|
45
|
+
"packages/testing/src/**/*.integration.test.ts",
|
|
44
46
|
],
|
|
45
47
|
};
|
|
46
48
|
|