feat: add personal skill storage, API, and SDK#25363
Conversation
Docs preview📖 View docs preview for |
|
/coder-agents-review |
217af13 to
37f4627
Compare
|
/coder-agents-review |
There was a problem hiding this comment.
Solid infrastructure PR. The resource follows the user_secrets pattern faithfully across all layers (migration, RBAC, dbauthz, audit, SDK) and deliberately diverges where it should (owner-role access). The trigger-based limit enforcement with FOR UPDATE serialization, the three-layer soft-delete protection, the split list/detail types omitting content from metadata, and the audit content masking are all well-reasoned. The migration comments earn their lines by explaining WHY, not WHAT.
Severity count: 1 P2, 5 P3, 1 P4, 4 Nit.
The P2 is a missing Is404Error check causing 500s on authorization failures. Two of the P3s interact: the deleted-user trigger's FOR UPDATE creates a deadlock path with soft-delete, and its untyped ERRCODE makes the race error uncatchable. The fix for both is the same: drop FOR UPDATE to match the user_secrets pattern and add a typed ERRCODE.
Test coverage is in stacked PR #25365 and not flagged here.
"The trigger comment explicitly states the rationale: Serialize skill-cap checks per user so concurrent inserts cannot all observe the same pre-insert count and exceed the hard limit. The trigger is the correct mechanism." (Pariston)
🤖 This review was automatically generated with Coder Agents.
There was a problem hiding this comment.
DEREM-3 (P2, missing Is404Error check) was addressed in 37f4627. Thanks for the quick fix.
13 findings from round 1 remain open with no author response or code change. Further review is blocked until these are addressed, acknowledged, or contested. The open items:
DEREM-4 (P3): FOR UPDATE deadlock path in deleted-user trigger
DEREM-5 (P3): Trigger ERRCODE uncatchable, producing 500
DEREM-6 (P3): 403 for quota exhaustion instead of 409
DEREM-7 (P3): No CHECK constraints for content size / name format
DEREM-8 (P3): Dual-sourced skill limit with no sync test
DEREM-1 (P3): Zero handler test coverage (pending stacked PR #25365)
DEREM-9 (P4): Unbounded skill name length
DEREM-10 (Nit): Message capitalization convention
DEREM-11 (Nit): Magic numbers in body-size formula
DEREM-12 (Nit): xerrors.Is vs errors.Is
DEREM-13 (Nit): Converters inline vs db2sdk
DEREM-2 (Nit): Raw constraint string vs typed constant
DEREM-16 (Note): Dead branch in trigger
For each, either push a fix, reply explaining why the current code is correct, or note that it's deferred with a ticket reference.
🤖 This review was automatically generated with Coder Agents.
37f4627 to
943fba4
Compare
|
/coder-agents-review |
There was a problem hiding this comment.
11 findings addressed in 943fba4. The deadlock fix (DEREM-4), typed ERRCODE (DEREM-5), CHECK constraints (DEREM-7), status code change (DEREM-6), name length cap (DEREM-9), and all nits look good. Substantial progress.
2 findings remain open with no author response:
DEREM-1 (P3): Zero handler test coverage. Thread was resolved in the GitHub UI but no code change and no comment. PR #25365 in the stack is titled "API test coverage." If that PR covers handler tests, a brief reply confirming that would unblock this.
DEREM-8 (P3): Dual-sourced skill limit (trigger hardcodes 100, Go constant says 100) with no sync test. Thread was resolved in the GitHub UI but no code change and no comment. Either add a test asserting the values match, or reply explaining why the comment-only coupling is acceptable.
Further review is blocked until these 2 items get a response (fix, acknowledgment, or ticket).
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
This is the third consecutive blocked round. 12 of 14 findings are addressed; the fixes look substantial and the panel needs to verify them. Two items are holding up that verification:
DEREM-1 (test coverage): A one-line reply on that thread confirming "Tests are in #25365" would unblock this.
DEREM-8 (dual-sourced limit): A one-line reply like "Accepted; the comment coupling is sufficient for this experimental feature" would unblock this.
No code changes needed. Just a reply on each thread so the panel can proceed to verify the 12 fixes.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
All 12 fixes from round 1 verified by the panel: deadlock eliminated (DEREM-4), trigger ERRCODE typed and catchable (DEREM-5), 409 for quota (DEREM-6), CHECK constraints added (DEREM-7), name length capped (DEREM-9), message casing (DEREM-10), named constants (DEREM-11), stdlib errors.Is (DEREM-12), converters in db2sdk (DEREM-13), dead branch removed (DEREM-16). Clean work.
DEREM-1 (test coverage): Panel accepts the stacked PR defense (3/3). Tests in approved #25365. Closed.
2 new findings this round: 1 P3 from Netero confirmed by 7/8 panel reviewers, 1 P3 from Bisky.
"The correction batch was systematic and root-cause-addressing. DB constraints were rewritten into the CREATE TABLE statement, not patched via ALTER TABLE after the fact." (Mafu-san)
🤖 This review was automatically generated with Coder Agents.
943fba4 to
dedac96
Compare
|
/coder-agents-review |
There was a problem hiding this comment.
DEREM-18 (name-length test) addressed in dedac96. Thanks.
1 finding remains: DEREM-17 (P3, patchUserSkill missing userSkillUserDeletedConstraint handling on UPDATE). Confirmed by 7/8 panel reviewers in round 5. The fix is ~3 lines mirroring postUserSkill at line 84. Either push the fix or reply on that thread explaining why the current behavior is acceptable.
🤖 This review was automatically generated with Coder Agents.
|
/coder-agents-review |
There was a problem hiding this comment.
DEREM-17 fixed in c4bd7c6. patchUserSkill now handles the deleted-user constraint on UPDATE, mirroring postUserSkill. Panel verified (4/4, no findings).
All 16 findings from this review are resolved: 15 fixed across 5 commits, 1 panel-closed (test coverage in stacked PR #25365), 1 acknowledged (dual-sourced limit acceptable for experimental scope). The fixes were systematic, root-cause-addressing, and introduced no regressions.
"The correction batch was systematic and root-cause-addressing. DB constraints were rewritten into the CREATE TABLE statement, not patched via ALTER TABLE after the fact." (Mafu-san, R5)
🤖 This review was automatically generated with Coder Agents.
c4bd7c6 to
20c907f
Compare
01003e4 to
10b94ad
Compare
|
/coder-agents-review |
There was a problem hiding this comment.
All 20 DEREM findings remain resolved. No new panel findings to raise.
CI is failing with 18 failures (gen, lint, fmt, test-go-pg, build, sqlc-vet, and more). These need to pass before merge.
8 @Emyrk threads are still Unresolved. Three are new since R9:
userskills.go:31: Why aren't the check constraint constants auto-generated intocheck_constraint.go?userskills.go:209: No rename path (delete and re-add). @Emyrk notes "fine for now."migrations/000498:13: Description column has no size constraint, unlike name and content.
Plus 5 from earlier rounds (auth-failure 404, deleted-user 404, owner role, userAdmin access, sync test). The author should respond to @Emyrk on each.
🤖 This review was automatically generated with Coder Agents.
> Mux updated this PR on behalf of Mike. ## Stack Context This stack splits experimental personal skills into smaller reviewable PRs. Personal skills are user-owned `SKILL.md` files stored by Coder and injected into chatd alongside workspace skills. Stack order: 1. #25362 personal skill resolver 2. #25363 storage, permissions, API, and SDK 3. #25365 API test coverage 4. #25366 chattool and chatd integration 5. #25066 settings UI and docs 6. #25386 personal skills slash menu ## What? Adds the shared personal skill parser and resolver package, plus reusable skill-name validation exported from `workspacesdk`. The parser enforces the full personal skill contract: max raw size, kebab-case name, max name length, and non-empty body. ## Why? The rest of the stack needs one source-aware resolver for personal and workspace skills, including collision handling and qualified aliases. Keeping personal skill constraints in the parser prevents callers from accidentally parsing invalid personal skills. ## Validation - `go test ./coderd/x/skills ./codersdk/workspacesdk` - pre-commit hooks on this branch
70e607f to
6c83f7d
Compare
Addressed the open #25363 review feedback in the latest head:
Validation is listed in the PR body. I am continuing to watch CI and review automation. |
|
/coder-agents-review |
There was a problem hiding this comment.
Post-@Emyrk changes verified by the panel (3/3). The RBAC model is now correctly scoped: owner gets read+delete only (no create/update), postUserSkill returns 403 for unauthorized creates, deleted-user errors are descriptive, description has a DB size constraint, and schema constants are guarded by a sync test.
All 20 DEREM findings resolved across 11 rounds. All 8 @Emyrk threads resolved. CI passing.
🤖 This review was automatically generated with Coder Agents.
6c83f7d to
6098a23
Compare
f123e0a to
97fd581
Compare
Stack Context
This PR is the storage, permissions, API, and SDK layer for experimental personal skills. #25362 has landed on
main, so this branch is restacked directly onmain.Stack order:
What?
Adds the
user_skillsdatabase table, generated queries, RBAC resources and scopes, audit resource handling, experimental user-scoped CRUD endpoints, SDK types, and generated API/site types.Follow-up review and restack fixes:
403 Forbiddenfor unauthorized create and update attempts.UserSkillMetadatain the fullUserSkillSDK response type.mainand renumber the user skills migration to000502_user_skills.Why?
Personal skills need durable user-owned storage with owner authorization, limited site-owner moderation, and a hidden API surface before chatd can consume them.
Validation
make gengo test ./coderd/database -run '^TestUserSkillSchemaConstants$' -count=1go test ./coderd/database/dbauthz -run '^TestMethodTestSuite/TestUserSkills$' -count=1go test ./coderd -run '^TestPatchUserSkill$' -count=1go test ./codersdk ./coderd/database/db2sdkmake lint97fd58108d