An AI coding workflow may generate probabilistic output, but its authority should not be probabilistic. Task state, approval scope, repository identity, and policy version are control data. If one of those values is malformed, silently coercing it is a dangerous default.
This is why the current discussion around SQLite strict tables is relevant to agent systems. At 2026-07-12 08:00 UTC, Evan Hahn's article “Prefer strict tables in SQLite” was the highest-scoring item in the Hacker News snapshot I reviewed, with 267 points. SQLite's own STRICT tables documentation is the source of truth for the feature.
The useful lesson is narrower than “make everything strict”: put strong boundaries around the small set of records that decide what an automated tool may do.
A control-data schema
CREATE TABLE agent_task (
task_id TEXT PRIMARY KEY,
repo_id TEXT NOT NULL,
requested_by TEXT NOT NULL,
state TEXT NOT NULL CHECK (
state IN ('queued', 'running', 'awaiting_approval', 'succeeded', 'failed', 'cancelled')
),
policy_version TEXT NOT NULL,
approved_commit TEXT,
approval_expires_at INTEGER,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
) STRICT;
CREATE TABLE tool_grant (
task_id TEXT NOT NULL REFERENCES agent_task(task_id),
tool TEXT NOT NULL,
resource_pattern TEXT NOT NULL,
effect TEXT NOT NULL CHECK (effect IN ('allow', 'deny')),
granted_by TEXT NOT NULL,
expires_at INTEGER NOT NULL,
PRIMARY KEY (task_id, tool, resource_pattern)
) STRICT;
STRICT does not create a complete authorization system. It does make invalid storage less ambiguous: values must be compatible with the declared types, and SQLite reports a constraint error rather than accepting arbitrary type substitutions. CHECK constraints still carry the domain rules.
Validate the decision, not only the row
Before a worker changes a repository, the application should evaluate all of these inputs together:
| Question | Reject when |
|---|---|
| Is this the intended repository? |
repo_id does not match the checked-out remote |
| Is the approval current? | expiry is in the past or absent for a privileged tool |
| Is the code revision pinned? |
approved_commit differs from the worker's base commit |
| Is the policy reproducible? |
policy_version cannot be loaded |
| Is the transition legal? | current and requested states are not an allowed edge |
A defensive transition can be one conditional statement:
UPDATE agent_task
SET state = 'running', updated_at = unixepoch()
WHERE task_id = :task_id
AND state = 'queued'
AND policy_version = :loaded_policy;
The worker proceeds only when exactly one row changed. That turns a race or stale assumption into a visible failure.
Threat model and limits
This boundary helps with accidental type coercion, illegal states, stale approvals, and concurrent transitions. It does not stop a process that can rewrite the database file, bypass the application, steal signing credentials, or alter the policy loader. File permissions, process isolation, append-only audit export, backups, and independent review remain separate controls.
Run PRAGMA integrity_check; as part of recovery testing, but do not confuse integrity with authorization. A structurally valid database can still contain a maliciously granted permission.
Where MonkeyCode fits
The public MonkeyCode repository describes an open-source AI coding platform with AI task, development-environment, model, and project-requirement management, plus private deployment. That makes control-data boundaries relevant when evaluating a deployment. The schema above is an independent review pattern; it is not a claim about MonkeyCode's internal database design.
Disclosure: I contribute to the MonkeyCode project. The observations and limitations below are based on the linked repository and the test setup described in this article.
If you are evaluating the platform, ask the team in the MonkeyCode Discord how task state, approvals, and policy versions are represented in the version you plan to run. You can also ask whether free model credits are currently available and confirm eligibility and usage limits.
The practical rule is simple: model output can remain flexible; the records that grant authority should fail closed.
Top comments (0)