fix(core/api): gate user + entity mutations#82
Merged
Conversation
Audit pass continues. This PR covers the user + onboarding endpoints:
every entity-fabrication and account-takeover primitive in core.
user.go
- CreateOrUpdateUser: create requires admin or sentinel:all (no
arbitrary user fabrication); update accepts the user themselves
via sub/user_id or the user:write scope (third-party app proxy),
plus the admin/internal overrides.
- DeleteUser: admin or sentinel:all only. No self-delete path
through this endpoint — account closure would go through a
different flow with proper cleanup.
onboarding.go (all sentinel:all only)
- CreateEntity: root identity creation, called by discord
onboarding via its SA bearer.
- CreateEntityEmailAuth: upserts email + password in one call —
the entire account-takeover primitive. Discord onboarding is the
only legitimate caller today; future password-reset flows would
layer their own token-mediated check before reaching here.
- CreateEntityPhoneAuth / CreateEntityExternalAuth: same trust
level — anyone able to write external_id rows can claim any
entity.
- UpdateEntityExternalAuthMetadata: refreshes cached provider
profile data; called by the oauth-discord-login flow.
entity.go
- CreateEntityLogin: audit log of token issuance. Reserved for the
oauth service — admins/users shouldn't be backdating their own
entries.
Internal callers (discord onboarding, oauth login, etc.) already
carry sentinel:all after PR #79, so existing flows keep working.
Anything outside Sentinel that was hitting these endpoints
unauthenticated will now get a 403.
This was referenced Jun 17, 2026
This was referenced Jun 17, 2026
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.
Stacked on top of #81 — base is `bk1031/harden-group-gates`. The diff shown here is just this PR's gates.
Audit holes covered
CRITICAL:
HIGH:
MEDIUM:
Gate model
All entity-mutation endpoints take `sentinel:all` only — they're internal primitives. The discord onboarding service and oauth login flow both carry sentinel:all on their SAs after PR #79, so existing flows are unbroken.
CreateOrUpdateUser splits create vs. update:
DeleteUser → admin or sentinel:all (no self-delete path here).
Test plan