@carllee1983/dbcli 7.0.0 → 7.0.1
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/dbcli.mdc +1 -1
- package/.cursor/skills/dbcli/reference.md +26 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/skills/dbcli/SKILL.md +1 -1
- package/.github/skills/dbcli/reference.md +26 -0
- package/CHANGELOG.md +14 -0
- package/assets/SKILL.md +1 -1
- package/assets/SKILL.zh-TW.md +1 -1
- package/assets/reference.md +26 -0
- package/dist/cli-runtime.mjs +1 -1
- package/dist/cli.mjs +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugins/dbcli-agent/.codex-plugin/plugin.json +1 -1
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +1 -1
- package/plugins/dbcli-agent/skills/dbcli/reference.md +26 -0
- package/skills/dbcli/SKILL.md +1 -1
- package/skills/dbcli/reference.md +26 -0
package/.cursor/rules/dbcli.mdc
CHANGED
|
@@ -639,7 +639,7 @@ schema. Raw `query` / `export` invocations render a sortable table only.
|
|
|
639
639
|
## Notes
|
|
640
640
|
|
|
641
641
|
- Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
|
|
642
|
-
- Blacklisted tables and columns are redacted from query output.
|
|
642
|
+
- Blacklisted tables and columns are redacted from query output. Every entry in `blacklist.tables` and `blacklist.columns` is a glob (`*`, `?`, `[a-z]`) on every engine, and a rule is compared against the whole dotted path case-insensitively — a rule spelled `password` also covers `Password`, and `profile.ssn` covers `profile.SSN`; a table literally named `report*` has to be written `report\*` to match literally again. `--fields` is unaffected and still matches exactly. A rule that cannot mean anything is rejected when the config loads rather than silently protecting nothing: a column entry qualified with its own table (`{"users": ["users.password"]}`) fails to load, and an unparsable rule makes every `dbcli es` request fail until it is fixed.
|
|
643
643
|
- `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in [reference.md](../skills/dbcli/reference.md#schema).
|
|
644
644
|
- `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
|
|
645
645
|
- **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `--timeout <ms>`, `--statement-timeout <ms>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
|
|
@@ -1102,6 +1102,26 @@ dbcli blacklist column remove users.password
|
|
|
1102
1102
|
|
|
1103
1103
|
**Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
|
|
1104
1104
|
|
|
1105
|
+
**Matching semantics (7.0.0):** every entry in `blacklist.tables` and `blacklist.columns` is a
|
|
1106
|
+
glob (`*`, `?`, `[abc]`, `[a-z]`) on **every** engine, not only Redis and Elasticsearch — `tables:
|
|
1107
|
+
["secrets*"]` blocks the SQL table `secrets_2026` and the MongoDB collection `secrets_2026` alike.
|
|
1108
|
+
A table literally named `report*` has to be written `report\*` to match literally again. Rules and
|
|
1109
|
+
returned names are compared over the **whole dotted path, case-insensitively**, so `password` also
|
|
1110
|
+
covers `Password` and `profile.ssn` covers `profile.SSN`; folding happens at the comparison and the
|
|
1111
|
+
config keeps rules as written. The cost is deliberate over-rejection: where PostgreSQL holds both
|
|
1112
|
+
`"Password"` and `"password"`, a rule naming either redacts both. `--fields` is unaffected and still
|
|
1113
|
+
matches exactly — it names keys in the document in front of the operator, not a protection rule.
|
|
1114
|
+
|
|
1115
|
+
Column-level entries are a **display filter, not an access control**: masking matches returned
|
|
1116
|
+
names, so `SELECT password_hash AS x` still returns the value. Table-level entries are the
|
|
1117
|
+
enforceable half.
|
|
1118
|
+
|
|
1119
|
+
A rule that cannot mean anything fails loudly instead of silently protecting nothing: a column entry
|
|
1120
|
+
qualified with its own table (`{"users": ["users.password"]}`) fails to load, and a rule the
|
|
1121
|
+
Elasticsearch shell cannot parse (`pass[word`, `a.**`) makes every `dbcli es` request fail until the
|
|
1122
|
+
config is fixed. Entries are trimmed and unquoted, and a rule filed under `public.users` applies to
|
|
1123
|
+
`SELECT * FROM users` and the reverse.
|
|
1124
|
+
|
|
1105
1125
|
**`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
|
|
1106
1126
|
document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
|
|
1107
1127
|
[{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
|
|
@@ -3547,6 +3567,12 @@ dbcli query "KEYS *" # → returns only non-blacklisted key
|
|
|
3547
3567
|
|
|
3548
3568
|
Rejections are written to the audit log with `success: false` and `metadata.rejection_reason: 'blacklist'` + `matched_pattern`.
|
|
3549
3569
|
|
|
3570
|
+
Enforcement covers `q` and `report` as well (7.0.0). Before that, saved queries and the built-in
|
|
3571
|
+
`@diag/redis-key-stats` diagnostic ran on an adapter that carried the connection but none of its
|
|
3572
|
+
rules, so `dbcli q @<name>` could read a protected key in plaintext and a report could persist
|
|
3573
|
+
protected key names. Both now resolve their key targets before execution, apply the connection's
|
|
3574
|
+
blacklist and `redis.mask` rules, and drop protected key names from `SCAN` evidence.
|
|
3575
|
+
|
|
3550
3576
|
### Value / hash-field masking (v1.22)
|
|
3551
3577
|
|
|
3552
3578
|
Where the key-glob blacklist *rejects*, masking instead *redacts*: a matched read still
|
|
@@ -639,7 +639,7 @@ schema. Raw `query` / `export` invocations render a sortable table only.
|
|
|
639
639
|
## Notes
|
|
640
640
|
|
|
641
641
|
- Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
|
|
642
|
-
- Blacklisted tables and columns are redacted from query output.
|
|
642
|
+
- Blacklisted tables and columns are redacted from query output. Every entry in `blacklist.tables` and `blacklist.columns` is a glob (`*`, `?`, `[a-z]`) on every engine, and a rule is compared against the whole dotted path case-insensitively — a rule spelled `password` also covers `Password`, and `profile.ssn` covers `profile.SSN`; a table literally named `report*` has to be written `report\*` to match literally again. `--fields` is unaffected and still matches exactly. A rule that cannot mean anything is rejected when the config loads rather than silently protecting nothing: a column entry qualified with its own table (`{"users": ["users.password"]}`) fails to load, and an unparsable rule makes every `dbcli es` request fail until it is fixed.
|
|
643
643
|
- `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in [reference.md](reference.md#schema).
|
|
644
644
|
- `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
|
|
645
645
|
- **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `--timeout <ms>`, `--statement-timeout <ms>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
|
|
@@ -1102,6 +1102,26 @@ dbcli blacklist column remove users.password
|
|
|
1102
1102
|
|
|
1103
1103
|
**Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
|
|
1104
1104
|
|
|
1105
|
+
**Matching semantics (7.0.0):** every entry in `blacklist.tables` and `blacklist.columns` is a
|
|
1106
|
+
glob (`*`, `?`, `[abc]`, `[a-z]`) on **every** engine, not only Redis and Elasticsearch — `tables:
|
|
1107
|
+
["secrets*"]` blocks the SQL table `secrets_2026` and the MongoDB collection `secrets_2026` alike.
|
|
1108
|
+
A table literally named `report*` has to be written `report\*` to match literally again. Rules and
|
|
1109
|
+
returned names are compared over the **whole dotted path, case-insensitively**, so `password` also
|
|
1110
|
+
covers `Password` and `profile.ssn` covers `profile.SSN`; folding happens at the comparison and the
|
|
1111
|
+
config keeps rules as written. The cost is deliberate over-rejection: where PostgreSQL holds both
|
|
1112
|
+
`"Password"` and `"password"`, a rule naming either redacts both. `--fields` is unaffected and still
|
|
1113
|
+
matches exactly — it names keys in the document in front of the operator, not a protection rule.
|
|
1114
|
+
|
|
1115
|
+
Column-level entries are a **display filter, not an access control**: masking matches returned
|
|
1116
|
+
names, so `SELECT password_hash AS x` still returns the value. Table-level entries are the
|
|
1117
|
+
enforceable half.
|
|
1118
|
+
|
|
1119
|
+
A rule that cannot mean anything fails loudly instead of silently protecting nothing: a column entry
|
|
1120
|
+
qualified with its own table (`{"users": ["users.password"]}`) fails to load, and a rule the
|
|
1121
|
+
Elasticsearch shell cannot parse (`pass[word`, `a.**`) makes every `dbcli es` request fail until the
|
|
1122
|
+
config is fixed. Entries are trimmed and unquoted, and a rule filed under `public.users` applies to
|
|
1123
|
+
`SELECT * FROM users` and the reverse.
|
|
1124
|
+
|
|
1105
1125
|
**`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
|
|
1106
1126
|
document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
|
|
1107
1127
|
[{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
|
|
@@ -3547,6 +3567,12 @@ dbcli query "KEYS *" # → returns only non-blacklisted key
|
|
|
3547
3567
|
|
|
3548
3568
|
Rejections are written to the audit log with `success: false` and `metadata.rejection_reason: 'blacklist'` + `matched_pattern`.
|
|
3549
3569
|
|
|
3570
|
+
Enforcement covers `q` and `report` as well (7.0.0). Before that, saved queries and the built-in
|
|
3571
|
+
`@diag/redis-key-stats` diagnostic ran on an adapter that carried the connection but none of its
|
|
3572
|
+
rules, so `dbcli q @<name>` could read a protected key in plaintext and a report could persist
|
|
3573
|
+
protected key names. Both now resolve their key targets before execution, apply the connection's
|
|
3574
|
+
blacklist and `redis.mask` rules, and drop protected key names from `SCAN` evidence.
|
|
3575
|
+
|
|
3550
3576
|
### Value / hash-field masking (v1.22)
|
|
3551
3577
|
|
|
3552
3578
|
Where the key-glob blacklist *rejects*, masking instead *redacts*: a matched read still
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to dbcli are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [7.0.1] - 2026-09-02 - agent 讀到的黑名單語意還停在 4.0.0
|
|
9
|
+
|
|
10
|
+
### Documentation
|
|
11
|
+
|
|
12
|
+
- **skill 的黑名單語意跟上 6.0.0 與 7.0.0。** `skill:check` 與 `plugin:check` 只驗結構、
|
|
13
|
+
清單項與 code token 對齊,不驗內容是否跟得上行為,於是 `assets/SKILL.md`、
|
|
14
|
+
`assets/SKILL.zh-TW.md` 與 `assets/reference.md` 在這兩版之間一個字都沒動——而這兩版改的
|
|
15
|
+
正是 agent 每次操作第一步要讀的東西。`reference.md` 的 `blacklist` 小節先前只列四個子指令,
|
|
16
|
+
現在寫明每個條目在所有引擎都是 glob(真的叫 `report*` 的表要寫成 `report\*`)、規則與回傳
|
|
17
|
+
名稱整條點分路徑不分大小寫、`--fields` 不受影響仍是精確比對、欄位層級是顯示過濾而非存取
|
|
18
|
+
控制,以及讀不出意思的規則會在載入時失敗而不是靜默不保護。Redis 的 Blacklist enforcement
|
|
19
|
+
小節補上 `q` 與 `report` 現在也強制執行、`SCAN` evidence 會移除受保護的 key 名稱。
|
|
20
|
+
`SKILL.md` 的 Notes 兩個語系同步擴寫。十份下游副本由 `plugin:sync` 帶上。
|
|
21
|
+
|
|
8
22
|
## [7.0.0] - 2026-09-02 - 一條規則擋得住寫、擋不住讀,差別只在大小寫
|
|
9
23
|
|
|
10
24
|
ADR-0019 在自己的 Consequences 裡寫下這一則:一份設定的大小寫折疊仍然是三套規則。
|
package/assets/SKILL.md
CHANGED
|
@@ -639,7 +639,7 @@ schema. Raw `query` / `export` invocations render a sortable table only.
|
|
|
639
639
|
## Notes
|
|
640
640
|
|
|
641
641
|
- Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
|
|
642
|
-
- Blacklisted tables and columns are redacted from query output.
|
|
642
|
+
- Blacklisted tables and columns are redacted from query output. Every entry in `blacklist.tables` and `blacklist.columns` is a glob (`*`, `?`, `[a-z]`) on every engine, and a rule is compared against the whole dotted path case-insensitively — a rule spelled `password` also covers `Password`, and `profile.ssn` covers `profile.SSN`; a table literally named `report*` has to be written `report\*` to match literally again. `--fields` is unaffected and still matches exactly. A rule that cannot mean anything is rejected when the config loads rather than silently protecting nothing: a column entry qualified with its own table (`{"users": ["users.password"]}`) fails to load, and an unparsable rule makes every `dbcli es` request fail until it is fixed.
|
|
643
643
|
- `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in [reference.md](reference.md#schema).
|
|
644
644
|
- `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
|
|
645
645
|
- **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `--timeout <ms>`, `--statement-timeout <ms>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
|
package/assets/SKILL.zh-TW.md
CHANGED
|
@@ -500,7 +500,7 @@ dbcli export "SELECT * FROM orders" --format html --output orders.html
|
|
|
500
500
|
## 備註
|
|
501
501
|
|
|
502
502
|
- Query-only 模式自動補 `LIMIT 1000`;查 `information_schema` 或會被 `LIMIT` 破壞的語句請加 `--no-limit`。
|
|
503
|
-
- 被 blacklist 的 table / column
|
|
503
|
+
- 被 blacklist 的 table / column 會從查詢輸出中遮蔽。`blacklist.tables` 與 `blacklist.columns` 的每個條目在所有引擎上都是 glob(`*`、`?`、`[a-z]`),規則與名稱比對時整條點分路徑都不分大小寫——寫成 `password` 的規則同時涵蓋 `Password`,`profile.ssn` 也涵蓋 `profile.SSN`;真的叫 `report*` 的表要寫成 `report\*` 才能回到字面比對。`--fields` 不受影響,維持精確比對。讀不出意思的規則會在設定載入時就被拒絕,而不是靜默地什麼都不保護:以自己的表限定的欄位項(`{"users": ["users.password"]}`)會載入失敗,無法解析的規則則會讓每一個 `dbcli es` 請求失敗,直到改掉為止。
|
|
504
504
|
- `schema` 回報 `estimatedRowCount` 與 `sizeCategory`(small / medium / large / huge)。大 / 巨大表要加 `WHERE` 或 `LIMIT` — 分界值見 [reference.md](reference.md#schema)。
|
|
505
505
|
- 對 `mongodb+srv://` 連線,`doctor` 會回報 SRV 是用原生解析或走 DoH fallback — 在執行環境限制 DNS 時很有用。
|
|
506
506
|
- **全域旗標:** `--version`、`--config <path>`、`--global`、`--use <name>`、`--timeout <ms>`、`--statement-timeout <ms>`、`-v` / `--verbose` / `-vv`、`-q` / `--quiet`、`--no-color`(也尊重 `NO_COLOR`)。除非指令明確宣告 command-level 選項,否則 root-level 旗標必須放在指令之前。
|
package/assets/reference.md
CHANGED
|
@@ -1102,6 +1102,26 @@ dbcli blacklist column remove users.password
|
|
|
1102
1102
|
|
|
1103
1103
|
**Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
|
|
1104
1104
|
|
|
1105
|
+
**Matching semantics (7.0.0):** every entry in `blacklist.tables` and `blacklist.columns` is a
|
|
1106
|
+
glob (`*`, `?`, `[abc]`, `[a-z]`) on **every** engine, not only Redis and Elasticsearch — `tables:
|
|
1107
|
+
["secrets*"]` blocks the SQL table `secrets_2026` and the MongoDB collection `secrets_2026` alike.
|
|
1108
|
+
A table literally named `report*` has to be written `report\*` to match literally again. Rules and
|
|
1109
|
+
returned names are compared over the **whole dotted path, case-insensitively**, so `password` also
|
|
1110
|
+
covers `Password` and `profile.ssn` covers `profile.SSN`; folding happens at the comparison and the
|
|
1111
|
+
config keeps rules as written. The cost is deliberate over-rejection: where PostgreSQL holds both
|
|
1112
|
+
`"Password"` and `"password"`, a rule naming either redacts both. `--fields` is unaffected and still
|
|
1113
|
+
matches exactly — it names keys in the document in front of the operator, not a protection rule.
|
|
1114
|
+
|
|
1115
|
+
Column-level entries are a **display filter, not an access control**: masking matches returned
|
|
1116
|
+
names, so `SELECT password_hash AS x` still returns the value. Table-level entries are the
|
|
1117
|
+
enforceable half.
|
|
1118
|
+
|
|
1119
|
+
A rule that cannot mean anything fails loudly instead of silently protecting nothing: a column entry
|
|
1120
|
+
qualified with its own table (`{"users": ["users.password"]}`) fails to load, and a rule the
|
|
1121
|
+
Elasticsearch shell cannot parse (`pass[word`, `a.**`) makes every `dbcli es` request fail until the
|
|
1122
|
+
config is fixed. Entries are trimmed and unquoted, and a rule filed under `public.users` applies to
|
|
1123
|
+
`SELECT * FROM users` and the reverse.
|
|
1124
|
+
|
|
1105
1125
|
**`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
|
|
1106
1126
|
document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
|
|
1107
1127
|
[{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
|
|
@@ -3547,6 +3567,12 @@ dbcli query "KEYS *" # → returns only non-blacklisted key
|
|
|
3547
3567
|
|
|
3548
3568
|
Rejections are written to the audit log with `success: false` and `metadata.rejection_reason: 'blacklist'` + `matched_pattern`.
|
|
3549
3569
|
|
|
3570
|
+
Enforcement covers `q` and `report` as well (7.0.0). Before that, saved queries and the built-in
|
|
3571
|
+
`@diag/redis-key-stats` diagnostic ran on an adapter that carried the connection but none of its
|
|
3572
|
+
rules, so `dbcli q @<name>` could read a protected key in plaintext and a report could persist
|
|
3573
|
+
protected key names. Both now resolve their key targets before execution, apply the connection's
|
|
3574
|
+
blacklist and `redis.mask` rules, and drop protected key names from `SCAN` evidence.
|
|
3575
|
+
|
|
3550
3576
|
### Value / hash-field masking (v1.22)
|
|
3551
3577
|
|
|
3552
3578
|
Where the key-glob blacklist *rejects*, masking instead *redacts*: a matched read still
|
package/dist/cli-runtime.mjs
CHANGED
package/dist/cli.mjs
CHANGED
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
|
@@ -639,7 +639,7 @@ schema. Raw `query` / `export` invocations render a sortable table only.
|
|
|
639
639
|
## Notes
|
|
640
640
|
|
|
641
641
|
- Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
|
|
642
|
-
- Blacklisted tables and columns are redacted from query output.
|
|
642
|
+
- Blacklisted tables and columns are redacted from query output. Every entry in `blacklist.tables` and `blacklist.columns` is a glob (`*`, `?`, `[a-z]`) on every engine, and a rule is compared against the whole dotted path case-insensitively — a rule spelled `password` also covers `Password`, and `profile.ssn` covers `profile.SSN`; a table literally named `report*` has to be written `report\*` to match literally again. `--fields` is unaffected and still matches exactly. A rule that cannot mean anything is rejected when the config loads rather than silently protecting nothing: a column entry qualified with its own table (`{"users": ["users.password"]}`) fails to load, and an unparsable rule makes every `dbcli es` request fail until it is fixed.
|
|
643
643
|
- `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in [reference.md](reference.md#schema).
|
|
644
644
|
- `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
|
|
645
645
|
- **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `--timeout <ms>`, `--statement-timeout <ms>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
|
|
@@ -1102,6 +1102,26 @@ dbcli blacklist column remove users.password
|
|
|
1102
1102
|
|
|
1103
1103
|
**Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
|
|
1104
1104
|
|
|
1105
|
+
**Matching semantics (7.0.0):** every entry in `blacklist.tables` and `blacklist.columns` is a
|
|
1106
|
+
glob (`*`, `?`, `[abc]`, `[a-z]`) on **every** engine, not only Redis and Elasticsearch — `tables:
|
|
1107
|
+
["secrets*"]` blocks the SQL table `secrets_2026` and the MongoDB collection `secrets_2026` alike.
|
|
1108
|
+
A table literally named `report*` has to be written `report\*` to match literally again. Rules and
|
|
1109
|
+
returned names are compared over the **whole dotted path, case-insensitively**, so `password` also
|
|
1110
|
+
covers `Password` and `profile.ssn` covers `profile.SSN`; folding happens at the comparison and the
|
|
1111
|
+
config keeps rules as written. The cost is deliberate over-rejection: where PostgreSQL holds both
|
|
1112
|
+
`"Password"` and `"password"`, a rule naming either redacts both. `--fields` is unaffected and still
|
|
1113
|
+
matches exactly — it names keys in the document in front of the operator, not a protection rule.
|
|
1114
|
+
|
|
1115
|
+
Column-level entries are a **display filter, not an access control**: masking matches returned
|
|
1116
|
+
names, so `SELECT password_hash AS x` still returns the value. Table-level entries are the
|
|
1117
|
+
enforceable half.
|
|
1118
|
+
|
|
1119
|
+
A rule that cannot mean anything fails loudly instead of silently protecting nothing: a column entry
|
|
1120
|
+
qualified with its own table (`{"users": ["users.password"]}`) fails to load, and a rule the
|
|
1121
|
+
Elasticsearch shell cannot parse (`pass[word`, `a.**`) makes every `dbcli es` request fail until the
|
|
1122
|
+
config is fixed. Entries are trimmed and unquoted, and a rule filed under `public.users` applies to
|
|
1123
|
+
`SELECT * FROM users` and the reverse.
|
|
1124
|
+
|
|
1105
1125
|
**`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
|
|
1106
1126
|
document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
|
|
1107
1127
|
[{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
|
|
@@ -3547,6 +3567,12 @@ dbcli query "KEYS *" # → returns only non-blacklisted key
|
|
|
3547
3567
|
|
|
3548
3568
|
Rejections are written to the audit log with `success: false` and `metadata.rejection_reason: 'blacklist'` + `matched_pattern`.
|
|
3549
3569
|
|
|
3570
|
+
Enforcement covers `q` and `report` as well (7.0.0). Before that, saved queries and the built-in
|
|
3571
|
+
`@diag/redis-key-stats` diagnostic ran on an adapter that carried the connection but none of its
|
|
3572
|
+
rules, so `dbcli q @<name>` could read a protected key in plaintext and a report could persist
|
|
3573
|
+
protected key names. Both now resolve their key targets before execution, apply the connection's
|
|
3574
|
+
blacklist and `redis.mask` rules, and drop protected key names from `SCAN` evidence.
|
|
3575
|
+
|
|
3550
3576
|
### Value / hash-field masking (v1.22)
|
|
3551
3577
|
|
|
3552
3578
|
Where the key-glob blacklist *rejects*, masking instead *redacts*: a matched read still
|
package/skills/dbcli/SKILL.md
CHANGED
|
@@ -639,7 +639,7 @@ schema. Raw `query` / `export` invocations render a sortable table only.
|
|
|
639
639
|
## Notes
|
|
640
640
|
|
|
641
641
|
- Query-only mode auto-appends `LIMIT 1000`; add `--no-limit` for `information_schema` or statements that break with `LIMIT`.
|
|
642
|
-
- Blacklisted tables and columns are redacted from query output.
|
|
642
|
+
- Blacklisted tables and columns are redacted from query output. Every entry in `blacklist.tables` and `blacklist.columns` is a glob (`*`, `?`, `[a-z]`) on every engine, and a rule is compared against the whole dotted path case-insensitively — a rule spelled `password` also covers `Password`, and `profile.ssn` covers `profile.SSN`; a table literally named `report*` has to be written `report\*` to match literally again. `--fields` is unaffected and still matches exactly. A rule that cannot mean anything is rejected when the config loads rather than silently protecting nothing: a column entry qualified with its own table (`{"users": ["users.password"]}`) fails to load, and an unparsable rule makes every `dbcli es` request fail until it is fixed.
|
|
643
643
|
- `schema` reports `estimatedRowCount` and `sizeCategory` (small / medium / large / huge). For large/huge tables add `WHERE` or `LIMIT` — bands in [reference.md](reference.md#schema).
|
|
644
644
|
- `doctor` on `mongodb+srv://` reports whether SRV resolves natively or through the DoH fallback — useful when the runtime restricts DNS.
|
|
645
645
|
- **Global flags:** `--version`, `--config <path>`, `--global`, `--use <name>`, `--timeout <ms>`, `--statement-timeout <ms>`, `-v` / `--verbose` / `-vv`, `-q` / `--quiet`, `--no-color` (also honours `NO_COLOR`). Root-level flags must precede the command unless the command explicitly declares a command-level option.
|
|
@@ -1102,6 +1102,26 @@ dbcli blacklist column remove users.password
|
|
|
1102
1102
|
|
|
1103
1103
|
**Subcommands:** `list`, `table add <name>`, `table remove <name>`, `column add <table.column>`, `column remove <table.column>`
|
|
1104
1104
|
|
|
1105
|
+
**Matching semantics (7.0.0):** every entry in `blacklist.tables` and `blacklist.columns` is a
|
|
1106
|
+
glob (`*`, `?`, `[abc]`, `[a-z]`) on **every** engine, not only Redis and Elasticsearch — `tables:
|
|
1107
|
+
["secrets*"]` blocks the SQL table `secrets_2026` and the MongoDB collection `secrets_2026` alike.
|
|
1108
|
+
A table literally named `report*` has to be written `report\*` to match literally again. Rules and
|
|
1109
|
+
returned names are compared over the **whole dotted path, case-insensitively**, so `password` also
|
|
1110
|
+
covers `Password` and `profile.ssn` covers `profile.SSN`; folding happens at the comparison and the
|
|
1111
|
+
config keeps rules as written. The cost is deliberate over-rejection: where PostgreSQL holds both
|
|
1112
|
+
`"Password"` and `"password"`, a rule naming either redacts both. `--fields` is unaffected and still
|
|
1113
|
+
matches exactly — it names keys in the document in front of the operator, not a protection rule.
|
|
1114
|
+
|
|
1115
|
+
Column-level entries are a **display filter, not an access control**: masking matches returned
|
|
1116
|
+
names, so `SELECT password_hash AS x` still returns the value. Table-level entries are the
|
|
1117
|
+
enforceable half.
|
|
1118
|
+
|
|
1119
|
+
A rule that cannot mean anything fails loudly instead of silently protecting nothing: a column entry
|
|
1120
|
+
qualified with its own table (`{"users": ["users.password"]}`) fails to load, and a rule the
|
|
1121
|
+
Elasticsearch shell cannot parse (`pass[word`, `a.**`) makes every `dbcli es` request fail until the
|
|
1122
|
+
config is fixed. Entries are trimmed and unquoted, and a rule filed under `public.users` applies to
|
|
1123
|
+
`SELECT * FROM users` and the reverse.
|
|
1124
|
+
|
|
1105
1125
|
**`list` options:** `--config <path>`, `--format <text|json>` (default: `text`). JSON writes one
|
|
1106
1126
|
document to stdout: `{ "tables": string[], "columns": Record<string, string[]>, "warnings":
|
|
1107
1127
|
[{ "collection", "raw", "reason" }] }`. Invalid MongoDB blacklist patterns appear in `warnings`;
|
|
@@ -3547,6 +3567,12 @@ dbcli query "KEYS *" # → returns only non-blacklisted key
|
|
|
3547
3567
|
|
|
3548
3568
|
Rejections are written to the audit log with `success: false` and `metadata.rejection_reason: 'blacklist'` + `matched_pattern`.
|
|
3549
3569
|
|
|
3570
|
+
Enforcement covers `q` and `report` as well (7.0.0). Before that, saved queries and the built-in
|
|
3571
|
+
`@diag/redis-key-stats` diagnostic ran on an adapter that carried the connection but none of its
|
|
3572
|
+
rules, so `dbcli q @<name>` could read a protected key in plaintext and a report could persist
|
|
3573
|
+
protected key names. Both now resolve their key targets before execution, apply the connection's
|
|
3574
|
+
blacklist and `redis.mask` rules, and drop protected key names from `SCAN` evidence.
|
|
3575
|
+
|
|
3550
3576
|
### Value / hash-field masking (v1.22)
|
|
3551
3577
|
|
|
3552
3578
|
Where the key-glob blacklist *rejects*, masking instead *redacts*: a matched read still
|