Repository navigation
Authenticate integrations with personal API tokens - #682
Merged
Merged
Conversation
EvilBrainsBot
pushed a commit
that referenced
this pull request
Oct 30, 2026
Member
Author
Code Review
Generated by Claude Code |
Member
Author
Code Review
Generated by Claude Code |
vdolek
previously approved these changes
Oct 30, 2026
Exported from the approved canvas artboard; the settings navigation of nastaveni.html gains the API tokeny entry. Export follows with #674. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
A token belongs to one user and acts as that user, tenant and role read from the user row on every request. It is evc_ plus 256 random bits, stored as its SHA-256 and found by a unique index, sent as a Bearer header; a policy scheme picks its handler by the prefix, so a token beside the access cookie wins. A boundary after authentication keeps a token out of /api/auth/** and token management (403) and refuses every write of a read-only token (403). An unknown, revoked or expired token is 401. Revocation deletes the row. The last use is stamped by a conditional update at most once a minute. Creation locks the user row, so two at once cannot pass the limit of 20 unexpired tokens. The OpenAPI document is anonymous in every environment and declares the Bearer scheme; Scalar stays Development only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
Labels move to /settings/labels and the new API token section is /settings/api-tokens; /settings redirects to the labels. Both pages share SettingsLayout, whose navigation lists the sections, so a later section is one entry and one page. The token section lists name, scope, created, expiry and last use, marks an expired token, creates a token with a name, a scope and a lifetime of 30, 90 or 365 days, shows the new token once with a copy button, and revokes a token through the confirmation modal. A new token defaults to read only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
ApiTokens carries the token hash and its last use moves every minute, so its migration gives it no history trigger; the convention tests still named RefreshTokens alone and failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
Serilog writes the completion event outside the token's log scope, so the request's own record named no token. The diagnostic context adds the token id and name to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
A token has no detail endpoint, so the created response carries no Location; SDD-005 names the exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
EvilBrainsBot
force-pushed
the
claude/project-thread-fyo2wf
branch
from
October 30, 2026 20:58
87e6753 to
55940a8
Compare
vdolek
approved these changes
Oct 30, 2026
vdolek
pushed a commit
that referenced
this pull request
Oct 30, 2026
<!-- claude-projects-attribution: {"github_login":"EvilBrainsBot"} -->
_Requested by **Martin** · [project
thread](https://claude.ai/code/project/chan_018WzBMUTj3Q3JGkpeCYsRag?thread=cmsg_018WzBMUTj3Q3JGkpeCYsRagTqdQm8Yo4J6YudBEHUPusZ)_
## Summary
An MCP server on `/mcp` for AI agents, authenticated by API token only,
with one-time links for file bytes. Stacked on #682, whose branch is the
base.
## Changes
- Stateless Streamable HTTP through the official SDK; anything but an
API token is 401, a foreign `Origin` 403; a read-only token lists and
calls only read tools.
- Tools for every SDD-005 resource with the contract DTOs, REST paging
and filters; errors are tool errors with the Problem Details title and
detail.
- `create_file_upload_link` / `create_file_download_link` on anonymous
`/api/file-links`: 256-bit secret stored hashed, 10 minutes, single use,
revoked with its token. The secret travels in the query string, which no
log records. The download link tool is a read tool.
- `read_file_text`: text formats, PDF, DOCX; 50,000-character pages; 30
MB limit.
- `/mcp` requests are logged like `/api`.
- SDD-023, SDDs 001/002/005/006/018, README, deploy.
## Risks
- The compose stack requires `EVILCASE_HOST`, which sets `AllowedHosts`.
- `CLAUDE.md` and the API rule still say every other path serves the
frontend: #685.
- If a token expires (rather than being revoked) within 10 minutes of
creating a file link, the link stays usable until it expires itself, and
SDD-023 only says that revoking a token ends its links.
- `dotnet r` could not run here (no pwsh, no .NET 8 runtime); format,
build and the changed test classes ran directly.
Closes #673
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UovdganawgyqDHGsank6jS)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Martin · project thread
Summary
Personal API tokens for integrations and agents, PR 1 of 2; the MCP server follows stacked on it.
Changes
evc_Bearer tokens with their own handler, picked by prefix ahead of the cookie; stored as SHA-256, read with the user row on every request./api/auth/**or/api/api-tokens; 401 for an unknown, revoked or expired token./openapi/v1.jsonanonymous in every environment, with the Bearer scheme./settings/labels,/settings/api-tokensand/settings/exportunder one layout;/settingsredirects.Deviations
.claude/rulesand the run-app skill still describe auth correctly and stay unchanged.ai-checkdid not run locally: no pwsh.Screenshots
Part of #673
https://claude.ai/code/session_01UovdganawgyqDHGsank6jS
Generated by Claude Code