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

15 KiB

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

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.