mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-17 00:16:46 +00:00
Three substantive issues raised by upstream review, encoded in code +
spec so future drift can't reintroduce them:
1. Width floor was unenforceable. The previous spec wording said
"form ≥ 360px / json ≥ 320px" but `react-resizable-panels` v3 only
accepts percentage `minSize`. On a 1280px viewport this could let a
user drag a pane down to ~250px — well below the documented floor.
- `Panel minSize` bumped 25 → 30 (≥ 30% of body width after rail)
- Spec rewritten percent-based with the actual 300–360px range
across realistic viewports plus a note on the v3 API constraint
and the `onResize`-clamp escape hatch if hard pixel floors become
necessary later.
2. `storageKey` default caused cross-page state bleed. The previous
default `storageKey="ccs.config-layout"` meant any `<ConfigLayout>`
without an explicit key would share localStorage state with every
other Config page — split ratios contaminating across unrelated
pages.
- `storageKey: string` is now REQUIRED (no default). TypeScript
compile-fails any caller that omits it.
- Spec restated to make the per-page-key contract explicit.
3. Sensitive-field heuristic was too narrow. The previous regex
`AUTH_TOKEN|API_KEY|SECRET|PASSWORD|PRIVATE_KEY` missed common
secret names (ACCESS_TOKEN, REFRESH_TOKEN, BEARER_TOKEN,
CLIENT_SECRET, CLIENT_ID, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
GCP/Azure/GitHub/OpenAI/Anthropic variants, JWT, OAUTH, CREDENTIAL,
PAT, WEBHOOK_SECRET, HMAC_KEY, SIGNING_KEY, SSH_KEY).
- New `src/lib/sensitive-label.ts` Single Source of Truth
(`isSensitiveLabel(label)`) with broadened regex; case-insensitive
and tolerant of `_`/`-` separators.
- `Field` imports the shared helper; future consumers do too.
- Spec §5g enumerates the new patterns and points at the SSoT.
Decisions log: v1.7 entry records the rationale and the connections
between spec wording and library API constraints, so the next reviewer
sees the trail rather than re-discovering it.
Validation: typecheck + lint + format clean; build clean; tests
519/521 pass (2 pre-existing account-visual-groups failures on dev,
unrelated). Styleguide demos already pass storageKey explicitly.
36 lines
2.0 KiB
TypeScript
36 lines
2.0 KiB
TypeScript
/**
|
|
* sensitive-label - Heuristic for detecting field labels that hold credentials
|
|
* or other secret-like values (per design-system.md §5g).
|
|
*
|
|
* Goal: catch the names secret-rotation tooling, OAuth flows, and cloud SDKs
|
|
* conventionally use. Anything matched here renders with the §5g treatment
|
|
* (lock + sensitive pill + masked input + reveal toggle) without the caller
|
|
* needing to set `sensitive` manually.
|
|
*
|
|
* The regex is intentionally permissive — false positives (e.g. a "PASSWORD
|
|
* STRENGTH" UI label that's not actually a credential) are recoverable
|
|
* (caller can pass `sensitive={false}` explicitly), whereas false negatives
|
|
* (a real credential rendered in plaintext) are a real leakage risk.
|
|
*/
|
|
|
|
const SENSITIVE_LABEL_PATTERN =
|
|
/(AUTH|ACCESS|BEARER|REFRESH|ID)[_-]?TOKEN|API[_-]?(KEY|TOKEN|SECRET)|CLIENT[_-]?(ID|SECRET)|(AWS|GCP|AZURE|GITHUB|GITLAB|OPENAI|ANTHROPIC|GEMINI)[_-]?(ACCESS[_-]?KEY|SECRET[_-]?(KEY|ACCESS[_-]?KEY)|TOKEN|PAT|API[_-]?KEY)|PRIVATE[_-]?KEY|SECRET[_-]?(KEY|ACCESS[_-]?KEY)?|PASSWORD|PASSPHRASE|SSH[_-]?KEY|JWT|OAUTH|CREDENTIAL|\bPAT\b|\bSECRET\b|\bSECRETS\b|SERVICE[_-]?ACCOUNT|WEBHOOK[_-]?SECRET|HMAC[_-]?KEY|SIGNING[_-]?(KEY|SECRET)/i;
|
|
|
|
/**
|
|
* Returns true if a field label looks like it holds a credential or secret.
|
|
* Match is case-insensitive and tolerates `_` / `-` separators.
|
|
*
|
|
* Matches include: AUTH_TOKEN, ACCESS_TOKEN, REFRESH_TOKEN, BEARER_TOKEN,
|
|
* API_KEY, API_TOKEN, API_SECRET, CLIENT_ID, CLIENT_SECRET, AWS_ACCESS_KEY_ID,
|
|
* AWS_SECRET_ACCESS_KEY, GCP_SERVICE_ACCOUNT_KEY, AZURE_CLIENT_SECRET,
|
|
* GITHUB_TOKEN, GITLAB_TOKEN, OPENAI_API_KEY, ANTHROPIC_AUTH_TOKEN,
|
|
* PRIVATE_KEY, SSH_KEY, JWT, OAUTH, CREDENTIAL, PAT, PASSWORD, PASSPHRASE,
|
|
* WEBHOOK_SECRET, HMAC_KEY, SIGNING_KEY.
|
|
*
|
|
* Does NOT match: USERNAME, EMAIL, USER_ID (identifier, not credential),
|
|
* SESSION_ID (not a long-lived credential), or unrelated field names.
|
|
*/
|
|
export function isSensitiveLabel(label: string): boolean {
|
|
return SENSITIVE_LABEL_PATTERN.test(label);
|
|
}
|