Skip to content

feat(skills): read-only built-in skills; fix(chat): allow CSV attachments - #11

Merged
squarezw merged 2 commits into
mainfrom
pr/skills-readonly-and-csv
Aug 6, 2026
Merged

feat(skills): read-only built-in skills; fix(chat): allow CSV attachments#11
squarezw merged 2 commits into
mainfrom
pr/skills-readonly-and-csv

Conversation

@squarezw

@squarezw squarezw commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Read-only built-in skills, and CSV attachments in chat

Two independent changes, both small and both front-end only.

1. Read-only state for built-in skills

The backend gains is_managed — skills that ship with the platform and sync
from the repo on each release. Users cannot edit or delete them.

The UI says why rather than making buttons vanish. A missing button reads as
a permission problem, and a user will go ask an admin for access that nobody
has. So the list shows a 「平台维护」 badge and a 查看 button, and the editor
drops its write actions instead of disabling them — a disabled button still
invites clicking.

canEditSkill checks is_managed first, ahead of the super-admin branch.
Super admins cannot edit these either: the constraint is not about privilege
level, it is that any edit gets silently overwritten by the next sync.

Falls back safely if the backend is older — is_managed undefined means the
skill is treated as ordinary.

2. CSV attachments in chat

CSV was rejected in chat although the backend has supported it all along
(file_processing_service.supported_extensions has a .csv handler, and
upload-confirm already labels the type). Nothing on the server side blocked
it; the presign endpoint does not check types at all.

Two front-end gates did, and they were two separately-maintained lists:
the accept attribute on the file input, and a MIME allowlist in
useFileAttachments. Both had drifted and both were missing .csv. Adding
the extension to only one of them produces a file you can pick but cannot
upload — so they are now merged into lib/chatAttachments.ts, with accept
derived from the extension list. They cannot diverge again, and a test asserts
it.

Validation is now extension-first with MIME as fallback. file.type comes
from the OS type registry and differs per machine for CSV: text/csv on
macOS, application/vnd.ms-excel on Windows with Excel installed, sometimes
an empty string. A MIME-only check would work on one machine and fail on a
colleague's with nothing in the error to explain why. The .ai special case
existed for exactly this reason; it is now the general rule rather than a
per-type patch.

MIME is kept as a fallback for files with no extension — pasted screenshots.

The list is aligned with the backend's supported extensions: anything that
uploads can be read by extract_document_text.

Tests

244 passed (was 229). tsc reports 135 errors against a baseline of 134; the
extra one is TS5097 on the new test file, the same error the repo's other 18
test files already produce (tests run under --experimental-strip-types, which
requires the .ts suffix that tsc rejects).

Mutation-verified: dropping .csv from the list turns 4 red; reverting to
MIME-only turns 6 red; changing endsWith to includes (which would let
note.csv.exe through as a CSV) turns 1 red.

Note on pairing

The read-only half pairs with the backend PR that adds is_managed. Merging
this first is harmless — the badge simply does not appear until the backend
ships. The CSV half is independent of both.

🤖 Generated with Claude Code

Jesse and others added 2 commits August 6, 2026 21:22
Needs ragent-service (`SkillResponse.is_managed`).

Built-in skills are maintained in the backend repo and sync in with each release,
so nobody can edit them — **including super admins**. That rule sits first in
`canEditSkill`: its answer is the same for everyone, and letting a super admin
through wouldn't be granting power, it would be handing them work that the next
sync silently overwrites.

## What changes visually

- List: a 「平台维护」badge next to the display name (hover explains it), and the
  row's actions collapse to 查看
- Detail: the title reads 查看 Skill, not 编辑 Skill — calling it "edit" when
  nothing on the page can be edited is a lie
- Detail: save / publish / submit-review are **removed**, not disabled — a row of
  greyed-out buttons invites repeated clicking on something that will never work.
  In their place, one sentence saying why, so the missing buttons don't read as a
  broken page
- The four content fields are disabled; the assets panel follows `canEditSkill`

`is_managed` missing (older backend) is treated as a normal skill — a field that
hasn't shipped yet must not lock down every skill.

## Verified in the browser

Against a backend carrying the new field: zero write buttons on a built-in skill,
all four content fields disabled, and the two remaining editable inputs are the
dependency picker's search boxes. Two display bugs found and fixed there — the
badge squeezed the display name into one character per line, and the stale title.

232 tests (+3), including the one pinning "super admin cannot edit either" — the
rule most likely to get loosened later by someone who knows super admins pass
everywhere else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e list

CSV was rejected in chat even though the backend has supported it all along
(file_processing_service.supported_extensions has a .csv handler, and
upload-confirm already labels it).

Two front-end gates blocked it, and they were two separately-maintained
lists — the accept attribute on the file input and a MIME allowlist in
useFileAttachments. Both had drifted and both were missing .csv, so adding
the extension to just one of them would have produced a file you can pick
but cannot upload.

Merged them into lib/chatAttachments.ts and derived accept from the
extension list, so they cannot diverge again.

Validation is now extension-first with MIME as fallback. file.type comes
from the OS type registry and differs per machine for CSV: text/csv on
macOS, application/vnd.ms-excel on Windows with Excel installed, sometimes
empty. A MIME-only check would have made this work on one machine and fail
on a colleague's with no visible reason. The .ai special case existed for
exactly this reason and is now the general rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@squarezw
squarezw merged commit 6184834 into main Aug 6, 2026
1 check passed
@squarezw
squarezw deleted the pr/skills-readonly-and-csv branch August 6, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant