fix(permissions): the service's own writes pass under core permission enforcement; the operation log cannot be edited (release/0.1 port of #52) #53

Merged
james.maes merged 2 commits from fix/system-writes-under-core-enforcement-0.1 into release/0.1 2026-11-12 17:37:21 +00:00
Owner

Port of #52 to the 0.1 release line. When a host enforces permissions inside core actions, the service's own system writes (the operation log row for every stored file among them) were refused by the QBit's own checker, so files were stored with no log row. The service now marks its own writes with core's per-call permission bypass; the checker refuses those tables to every session, the system user included. A failed log row is now an error, an alert and a count. Reviewed independently on #52; full build green on this branch.

🤖 Generated with Claude Code

Port of #52 to the 0.1 release line. When a host enforces permissions inside core actions, the service's own system writes (the operation log row for every stored file among them) were refused by the QBit's own checker, so files were stored with no log row. The service now marks its own writes with core's per-call permission bypass; the checker refuses those tables to every session, the system user included. A failed log row is now an error, an alert and a count. Reviewed independently on #52; full build green on this branch. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 2 commits 2026-11-12 17:36:16 +00:00
fix(permissions): let the service write its own tables when core actions enforce permissions
maven / build (push) Successful in 3m40s
build / maven (push) Successful in 3m40s
a1ff8b6369
In a host that sets QInstance.enforcePermissionsInCoreActions, core checks
table permissions inside InsertAction, UpdateAction and DeleteAction for
every outermost call. Db.asSystem starts a new context, so each write it
makes is outermost, and core asks ObjectStoragePermissionChecker about it.
The checker refused every write of a table that is not admin-editable
("This storage table changes only through storage actions.") to every
session, the system user the service itself writes as included.

Seen in a host application: every StorageBucket.put stored the object and
logged "Could not write a storage operation log row" with
QPermissionDeniedException, so object_storage_operation had no row for any
stored file. The same refusal applies to every other Db.asSystem write of
those tables.

The checker now lets a QSystemUserSession through for those tables. Such a
session is built by server code only; no authentication module gives one
to a request. A person is refused as before, the storage administrator
included (DbSystemSessionTest
.testServiceWritesItsOwnTablesWhenCoreActionsEnforcePermissions, which
failed before with no operation row).

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
fix(permissions): mark the service's own writes with the core bypass; report a failed audit row
maven / build (push) Successful in 2m53s
build / maven (push) Successful in 2m53s
59b0ea2ed6
Review of the first fix found the checker's pass too broad: it let any
QSystemUserSession insert, update and delete every table nobody may write
directly, so server code running as the system user could edit or delete
operation log rows.

- ObjectStoragePermissionChecker no longer looks at the session class. A
  write of those tables that reaches it is refused to every session, the
  core system user included.
- Db.insert, Db.update and Db.delete mark their input with core's per-call
  permission bypass (withPermissionBypass, Db.OWN_WRITE_REASON), so core
  does not ask about the service's own writes when a host enforces
  permissions inside the core actions.
- A failed operation log row is logged at ERROR, raises the
  storage.operation_log.failed alert on the StorageAlertSink (resolved by
  the next row written for the bucket) and is counted in
  OperationLog.failedWriteCount(). A row the insert action hands back with
  a record error is now detected too. The operation still succeeds.

Tests: the service's own log, index insert, update and delete under core
enforcement, with the acting person on the row; a system session outside
Db refused insert, update and delete of an operation row; update and
delete of an operation row refused to a person, the administrator and the
system user; the failure signal.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
james.maes merged commit 3473cf62bc into release/0.1 2026-11-12 17:37:21 +00:00
Sign in to join this conversation.