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>
Host-neutral help (deployment-specific facts removed), registered with
HelpBundles, gated by HelpBundleAssertions. QQQ 4.1.0-RC.7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- effective limit is min(code, row); row 0/null/higher is ignored; config never mutated
- applied to presignGet/Put/Post, previewUrl and the download-link action; row read cached 15 s
- Setup card takes connections and buckets from the runtime config and counts rules as system
- seed changeset rollback is empty; test that a host rule survives rollback
- host help kept test, stand-in marker prose in the bundle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Help bundle for all 12 tables and the app (ObjectStorageHelp), Setup card on
the home, disabled default-mutable header rule via a jar changelog tested
through real Liquibase on H2, tables guardrail test. The bucket row's presign
limits are now read at runtime (ConfigSync.withBucketOverrides). The version
table is documented as reserved and not used yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ConnectionRuntime maps StorageConnectionConfig to S3BackendMetaData and
builds clients with core S3ClientFactory.buildClient, which is uncached.
The per-connection cache keyed by the settings hash is unchanged.
The duplicated HTTP, TLS and trust-manager code is deleted.
Still local:
- the presigner;
- a session-credentials bridge, because core has no session-token or
credentials-provider hook;
- ${file.PATH} secret refs.
The last two are tagged STAND-IN(core=QRun-IO/qqq#1165, removeBy=4.1.0-RC.7).
Retries now follow core and SDK defaults instead of a forced ADAPTIVE_V2.
Unused SFTP/SSH transitive dependencies of the filesystem module are
excluded.
Closes#10 (architecture review QRun-IO/qqq#1150, finding F3).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ObjectStorage.configureStandalone(config) for CLI tools and tests (no QInstance)
- FieldReferenceProvider.keyFolder(...) for key-per-folder references
- child lists on record screens show a curated column set
- README and CHANGELOG rewritten (usage, deployment, owner steps)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Maven scaffold (qbit-build-parent 2.0.0, com.kingsrook.qbits, <revision>
versioning, qqq 4.1.0-RC.4 BOM, JaCoCo gate), QBit config and producer,
CircleCI qqq-orb pipeline, and the standard repository files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>