Files
qbit-scripting/docs/DURABLE-AFTER-HOOKS.md
f0d695ec97
QRun-IO/ci-policy: ci / fork-guard (push) Skipped
QRun-IO/ci-policy: ci / head-profile (push) Skipped
QRun-IO/ci-policy: ci / application-template-0 (push) Skipped
QRun-IO/ci-policy: ci / gradle-1 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (push) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (push) Skipped
QRun-IO/ci-policy: ci / node-8 (push) Skipped
QRun-IO/ci-policy: ci / node-9 (push) Skipped
QRun-IO/ci-policy: ci / node-10 (push) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (push) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (push) Skipped
QRun-IO/ci-policy: ci / source-config-13 (push) Skipped
QRun-IO/ci-policy: ci / source-config-14 (push) Skipped
QRun-IO/ci-policy: ci / android-0 (push) Skipped
QRun-IO/ci-policy: ci / original-business (push) Skipped
QRun-IO/ci-policy: ci / original-mcp (push) Skipped
QRun-IO/ci-policy: ci / original-voyage (push) Skipped
QRun-IO/ci-policy: ci / original-cli (push) Skipped
QRun-IO/ci-policy: ci / repository-policy (push) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (push) Skipped
QRun-IO/ci-policy: ci / not-enrolled (push) Failing after 7s
QRun-IO/ci-policy: native / fork-deny (push) Skipped
QRun-IO/ci-policy: native / dotnet-0 (push) Skipped
QRun-IO/ci-policy: ci / ci-result (push) Failing after 6s
QRun-IO/ci-policy: native / native-result (push) Successful in 6s
chore: preserve paused QBit work and document remaining issues
Save the current implementation and README, status, and known-issue documentation at the user-requested stop. No completed release or deployment is claimed.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: GPT-6 Codex <noreply@openai.com>
2026-11-04 10:45:28 -06:00

240 lines
15 KiB
Markdown

# Durable AFTER record hooks
Status: full base verification passed 2026-10-31 against the root-verified core/RDBMS
candidate in a dedicated local repository: 145 tests, no failures/errors/skips,
zero Checkstyle violations, unchanged instruction/branch coverage checks passed.
The 13 native file-H2 AFTER tests use the real transactional Jobs owner/runtime
and a trusted protocol worker. The corrected optional provider gate also passed all 44 tests: 13 file-H2,
14 actual AFTER/MySQL and 17 baseline MySQL. This is not a hostile-worker or
deployment qualification.
No new queue, script registry, database store or generation dependency was added.
## Event semantics
Add distinct AFTER_INSERT, AFTER_UPDATE and AFTER_DELETE phases. Existing PRE and
POST behavior is unchanged: POST observes the backend action before its caller
may commit, and a warning cannot undo that action. AFTER is dispatched from a
Jobs intent enlisted in the exact source transaction and becomes deliverable only
after commit. Enlistment failure refuses the required mutation; delivery failure
cannot roll back its committed source. Preview never enlists or executes AFTER.
INSERT/UPDATE retain only a bounded locator and immutable script pin. The worker
receives a newly authorized, field-projected record at delivery time, explicitly
not the historical mutation snapshot. A deleted/missing/inaccessible current row
refuses execution. DELETE is an event-metadata notification, not an old-record
snapshot: no deleted values or inferred missing-row readability. Current native
table/action/project/run authority is still mandatory. Jobs parameters contain
no source record field snapshot, passwords, BLOBs, hidden fields or credentials.
## Minimal components
- Extend HookEvent and ALLOW-only result validation. AFTER cannot patch or veto;
the broker remains bounded read-only. SDK event metadata explains delivery
semantics; authoring discovery/test/binding uses the existing APIs.
- An opt-in host metadata helper installs a required transactional record listener
for selected AFTER phases, preserving existing Java customizers and refusing
conflicting required listeners rather than silently replacing them.
- The listener resolves the active immutable binding, publication/build/artifact
pin, checks current caller authority and bounds the action/locator count. A
core-owned UUID identifies this exact active native event invocation; per-record request
keys include that identity, binding ID and ordinal. Repeated callback enlistment
therefore reuses the same owner key without a consumer registry. Identical later writes
are different events. Re-delivery of the persisted job preserves its event ID.
- A single fixed Java backend process (stable transactional process revision)
consumes only a core-verified currently leased enlisted intent. Direct process
invocation and an ordinary launched Jobs process with forged parameters fail.
The consumer must not duplicate core grant/lease verification or trust params
as credentials.
- Delivery checks current restored actor, native table/action and project access,
enabled exact binding, immutable publication/build/artifact hashes, field
policy and qualified worker. INSERT/UPDATE use genuine enforced native Get
with display/heavy enrichment disabled. DELETE rechecks table-level policy
using a genuine read input and does not fetch or expose deleted values.
- Existing append-only script execution audit records attempts/outcomes with
event correlation and generic host-owned refusal codes. Worker text and source
values stay out of shared history. Core Jobs owns admission, restart, attempts,
lease and completion; no exactly-once script execution claim. A crash between
external execution and completion can repeat an observational attempt. Terminal
audit failure after worker execution leaves the job failed and the independently
committed STARTED entry visible. An authorized operator retry may run the worker
again with the same event correlation; that ID is not execution deduplication.
## Compatibility and verification
MySQL fresh schema includes the nine phases; `003_durable_after_hooks.sql` upgrades
the original unnamed event check after explicit schema inspection. H2 metadata-derived
fixtures have no event check to migrate. Existing rows
and published source pins retain their meaning. Native authoring lists AFTER only
when the host installs its required listener; patch fields remain empty and dry
runs explicitly do not prove commit or enqueue jobs. No worker runtime change.
Use real native InsertAction/UpdateAction/DeleteAction and qualified JDBC/Jobs
fixtures with a trusted protocol worker: source+intent commit/rollback and caught
admission failures; preview suppression; bounded batch locators; identical later
writes remain distinct; repeated same request dedupes/conflicts correctly;
restart restores current actor and pinned script; revoke project/table/run/binding
before delivery and prove zero worker calls; hidden/credential data never enters
params/context; deleted snapshot never enters worker; direct invocation refused;
ALLOW accepted and PATCH/VETO rejected; audit failure explicit; late source
update produces authorized current-state data. Tests must not substitute a fake
queue for native same-transaction/restart evidence.
Core dependencies are not installed by this task. Root coordinates final shared
artifact handoff, provider gates and consumer compatibility builds.
## Host registration and authoring
```java
ScriptAfterHooks.install(instance, sourceTable,
HookEvent.AFTER_INSERT, HookEvent.AFTER_UPDATE, HookEvent.AFTER_DELETE);
```
Configure the existing native Jobs provider on the same supported transaction
resource as the source table, enable transactional admission, and provide the
operator-owned namespace/grant key and identity restoration. The scripting QBit
does not provision or weaken those controls. Bind a tested immutable publication
through normal authorized hook administration. The source editor advertises
AFTER only for installed source phases. Dry runs use a current selected record
for authorization, produce `dryRun: true`, never enlist, and cannot attest commit.
Setting an event string in a direct request never supplies the native dispatch
marker: the fixed delivery entry point always calls the core verifier itself.
The generated editor SDK and bundled compiler SDK declare `HookEvent` (nine
phases) and `CommittedEvent`, whose `CURRENT` variant has a projected `record`
and whose `DELETED_METADATA` variant has no record. These are type assistance,
not authority. Core lease/grant/session checks run on entry, at the actual worker
boundary after history/artifact host callbacks, and after delivery.
Trusted SDK verification: worker/after-sdk-tests.log (18 passed),
worker/after-sdk-lint.log; frontend scripting-after-ui-tests.log (15 passed) and
scripting-after-ui-lint.log. Compiler SDK source SHA256
579ad147e7e0d4f2e025e4513fa8d6ad0436870872b64cb4ce4907ad9eec986a;
worker test source bda2208680b50d81132affb845746ce75d4445aa21b0f594b1cc7ea16f2be5cd.
Root subsequently built and sealed the separate 0447 SDK image candidate;
sealed 0240 image evidence remains unchanged. Runtime qualification remains separate.
## Historical initial native evidence and compatibility boundary
`after-hooks-full-verification.log` is the successful full base gate. The earlier
focused 19-test run found two wrong exception-class assertions; actual native
required listeners throw RequiredListenerException. The corrected 20-test gate
passed before the final full run. Tests preserve source rollback and failed
commit assertions. Existing PRE/POST tests explicitly select their six phases;
AFTER has separate host registration.
The native tests prove source/intent shared commit and rollback, preview refusal,
required-listener admission poisoning even when caught, bounded batches, distinct
identical later mutations, restart with pinned publication and current-state
projection, metadata-only deletion, run/project/source/binding revocation, direct
non-enlisted process refusal, pre-worker scope changes refused after STARTED, and
post-worker scope changes refusing job completion. STARTED audit failure prevents
the worker; outcome audit failure can follow a real execution, and explicit
authorized retry executes again with the same event correlation.
Verified main JAR SHA256:
`d56cae9d674856b3b8eca68e499896d78f59970b73eee50ef88228d17c207cba`;
tests JAR `2209b33413512d7029c6564ddb7215c0f815732915e341048d5848ff8ef30cd7`.
Exact source manifest: `target/after-hooks-verified-source.json`. The core/RDBMS
prerequisite full gates are 3203/417 tests with 16 existing skips; subsequent
29-test native statement-cleanup gate and exact artifact handoff are parent-owned.
H2 evidence does not establish a combined AFTER consumer/MySQL execution test.
Core transactional Jobs has its own actual MySQL provider gate; the optional
scripting RDBMS provider compatibility suite remains a distinct gate. Production
identity restoration, operational namespace/key rotation, actual isolated worker
qualification, and deployment recovery policy remain host responsibilities.
## Historical provider and editor follow-up before the corrected gate
Test-only provider seams preserve all 13 AFTER scenarios and their assertions;
they pass again on actual file-H2 (`after-hooks-provider-seams-verification.log`).
The production main JAR is byte-identical to the full145 gate. Regenerated test
JAR SHA256 is `ec304ab4e191c4a7e4ffca30fe48bb73ee8511e84a6224471589cad57ed842f7`.
Only the base AFTER fixture changed relative to the original source manifest.
The optional MySQL subclass uses the existing pinned provider factory, DML-only
application identity, real scripting policy, native Jobs qualification and shipped
scripting migration/triggers. Jobs adds mandatory READ_COMMITTED and bounded DDL
lock wait. Its restart scenario restarts the actual server and refreshes the
inspected dynamic port before recovering the queued intent. There is no weaker
provider/schema substitute. Full42-provider execution is pending.
The previous optional29 gate had one MySQL communications failure (the generic
qualification refusal intentionally carries no SQL/credentials). A separate
unchanged-deadline retry of that exact method passed with running=true,
oomKilled=false, restarts=0. It does not establish the original failure's cause
or justify calling it transient. Bounded test-only exception class/SQLState and
policy-method diagnostics remain enabled for the combined gate; they never log
SQL, messages, connection properties or credentials.
The offline editor fallback SDK also now matches the generated/server and bundled
compiler SDK. Actual language-service tests cover completion of all nine hook
phases plus CONTEXT, invalid event diagnostics and deleted-record narrowing.
Combined frontend API/panel/language-service22 tests and scoped ESLint pass in
`scripting-after-sdk-ui-tests.log` and `scripting-after-sdk-ui-lint.log`. No package
or lockfile changes accompany these declarations.
## Corrected audit schema and final provider gate — 2026-10-31 05:26
The first combined42 gate (`rdbms/after-hooks-combined-provider-verification.log`)
failed five AFTER/MySQL assertions and one baseline MySQL setup. The five AFTER
failures exposed a real schema defect: UUID plus ordinal correlation needs at
least 38 characters, while the old physical audit column allowed 36. Producer
metadata and fresh001 now use VARCHAR(64); actual003 widens existing history
before enabling nine-phase bindings. Event identity and retry assertions were
not shortened or weakened. The upgrade test preserves every column of two real
pre-upgrade audit rows and verifies their UPDATE/DELETE guards after migration,
then records STARTED/OK with the exact long event correlation.
The optional policy now checks the exact current transaction's mapped execution
column: VARCHAR, capacity at least64 and NOT NULL, using a bounded metadata SELECT.
Unmigrated36 and nullable columns refuse before worker execution or new audited
work. There is no qualification cache, second connection or runtime DDL.
`after-hooks-correlation-full.log`: full145 base tests, zero failures/errors/skips,
Checkstyle and unchanged coverage gates passed. `rdbms/after-hooks-capacity-h2-verification.log`
passed13 file-H2 tests. Root's `rdbms/after-hooks-operation64-provider-verification.log`
passed44 tests at05:26:08:13 file-H2,14 actual AFTER/MySQL and17 baseline MySQL,
zero failures/errors/skips and Checkstyle clean. The actual AFTER scenarios use
native Jobs admission/delivery, DML-only application identity, shipped migrations,
restart, rollback, current-authority refusal and audit-failure retry.
Exact corrected artifacts (SHA256):
- Base main: `9d205a77b155cb59360b24f3e5b38d139df24f9548398e62d3ed789c042d0c1d`.
- Base tests: `b6a9db73a761014a322a2551a169fb6eb036b343bd7ee58e342c94d5a0bc11c2`.
- Base POM: `987b2e5456a22b07ce1601c57ea6f50e4d44b21491de53ff6c5048feaa2ff1bd`.
- Optional RDBMS JAR: `2ff374cb881be26b331e9db9ec8fc20a8ea694ee49017b3ba81c5341217cd989`.
- Optional POM: `6be71c8fe8d727f0047c0ce5c2edf50b2e2785d2fa746db6589256770a9c547c`.
Base source manifest: `target/after-hooks-operation64-source.json`; combined
source/artifact manifest: `target/after-hooks-operation64-provider-source.json`.
Only the dedicated local Maven repository received base artifacts; no shared
installation or deployment occurred. Optional middleware/GitHub compatibility
is recorded separately after its own gates.
The earlier12954 qualification/transport failure and6946 baseline08S01 failure
remain preserved. A single-method diagnostic retry and this full corrected gate
passed unchanged deadlines, with healthy fixture observations; they do not
establish those original transport failures' cause or justify calling them
transient. Only the separately reproduced audit-width defect is diagnosed and
corrected here. Production storage/recovery, identity restoration and hostile
worker qualification remain deployment gates.
### Optional consumer compatibility
After the corrected145/44 snapshot, serial offline wrapper verification in the
same dedicated repository passed middleware7 (including6 actual native HTTP
tests) at05:27:44 and GitHub importer7 at05:28:37, with Checkstyle and no installs.
Logs: `middleware/after-hooks-operation64-compatibility.log` and
`github/after-hooks-operation64-compatibility.log`. GitHub tests use trusted
HTTP fixtures; no private repository was sent externally.
Middleware JAR SHA256 `4094e2d7b74906fda6dd98ff6e879fa38aec7cd8489ae8681b1c196fb21fe936`;
GitHub JAR SHA256 `63b2ed1a8ecae02fc2d37754ab552a5133525a20087865120b0c4bc7fbc1c300`.
Their exact source, POM and artifact hashes are appended to
`target/after-hooks-operation64-provider-source.json`. No production source changed
during these compatibility gates. These existing HTTP tests establish regression
compatibility; native durable AFTER delivery is exercised by the separate13/14
H2/MySQL fixtures, not by an invented HTTP commit assertion.