Skip to content

feat(security): grants on types, capabilities, password expiry and connection limits - #114

Merged
venkat1701 merged 9 commits into
mainfrom
feature/permissions
Oct 27, 2026
Merged

venkat1701 merged 9 commits into
mainfrom
feature/permissions

Conversation

@venkat1701

@venkat1701 venkat1701 commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #113.

Full build of this branch: engine 257, database 143, server 41, all passing.

…nnection limits

- ROLE none: no data access until GRANT READ|WRITE ON TYPE. An atom of
  a type the user cannot read is invisible exactly like another
  tenant's, through the same Reader checks; naming such a type in
  MATCH, RANK, PATTERN or HORA fails with no READ privilege. Writes
  need WRITE on the changed atom's type.
- GRANT MONITOR (STATS, Studio dashboard) and GRANT MAINTAIN
  (CHECKPOINT, CHECKPOINT AT, COMPACT) let default-tenant users operate
  the engine without being global admins.
- ALTER USER ... ROLE, VALID UNTIL and CONNECTION LIMIT, in any
  combination with PASSWORD. Expired passwords fail like wrong ones;
  connection limits count signed-in sessions and spare global admins.
- The last admin of the default tenant cannot change its role or be
  dropped while other users remain.
- SHOW GRANTS, and SHOW USERS lists expiry and connection limit.
- Grants and user options live in their own slots (75, 76), so
  existing user records are untouched.
- ROLE none no longer sees evidence or assertions (TRACE), which belong
  to the tenant rather than to a type.
- A key reference to an unreadable type fails with the privilege error
  whether or not the key exists.
- DELETE by a ROLE none user needs WRITE on every hyperedge of its
  tenant that holds the atom, since deleting removes those memberships.
- Grants are read from the latest committed main, so a revoke applies
  inside open transactions and AT GENERATION cannot restore it.
- EXPLAIN for ROLE none estimates index ranges blindly and skips the
  tenant's cardinality feedback.
- Set algebra INTO checks the members it copies.
- A Studio login that cannot open a session releases its connection.
- Removing, demoting or expiring an admin of the default tenant needs
  another admin who can sign in, and places a commit-time precondition
  on those admins, so concurrent removals cannot both commit.
- Only global admins change the role, expiry or connection limit of an
  admin.
- Password expiry is checked after the SCRAM proof; sessions ended by
  a credential change stay ended until they sign in again.
- hstore check and --repair-tenants cover every active branch, and the
  boundary tests also cover raw transactions and engine snapshots.
# Conflicts:
#	database/src/main/java/io/hstore/db/query/Session.java
#	database/src/main/java/io/hstore/db/security/Security.java
#	docs/database/security.md
#	docs/operations/cli.md
#	docs/operations/logging.md
- A merge used only as a guard changed nothing, so its slot did not
  count as touched and the fast path skipped the precondition. Every
  slot a transaction writes to now counts.
- The default tenant keeps an admin whose password never expires, and
  the check also guards the other admins' options records.
- CREATE USER clears leftover grants and options; GRANT, REVOKE and
  ALTER USER guard the user's record against a racing DROP USER.
- Signing in again as the same user keeps one connection count, idle
  Studio sessions are swept in the background, and tenants get a
  connections quota.
- Writer.load checks write access before loading no members.
- CREATE, ALTER and DROP USER all check that a never-expiring global
  admin remains, and guard the ones that do, so a create racing the
  drop of the last admin cannot commit.
- ALTER USER always guards the user's record, even when it restates
  the current role.
- Signing in again gives back the old count before taking the new
  one, so a user recreated in another tenant is counted there.
- A closed session runs nothing; closing always releases its count.
- The connections quota key ignores case.
- A tenant admin cannot set another admin's password.
- The Studio sweeper survives failures and does not interrupt writes.
Requiring every database to start with a global admin refused embedded
setups that create tenant users first. The rule now applies as soon as
a global admin exists, which still refuses dropping the last one and
creating other users in the same or a concurrent transaction.
# Conflicts:
#	database/src/main/java/io/hstore/db/Reader.java
#	database/src/main/java/io/hstore/db/Writer.java
#	database/src/main/java/io/hstore/db/query/Session.java
#	database/src/main/java/io/hstore/db/security/Security.java
#	docs/operations/wire-protocol.md
#	docs/transactions/transactions.md
@venkat1701
venkat1701 changed the base branch from feature/tenant-boundary to main October 27, 2026 12:27
@venkat1701
venkat1701 merged commit 8d0dc60 into main Oct 27, 2026
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