Technology · Discipline

Schema-agnostic data access and SQL-injection defence

Database access in generated code goes through a schema resolver that validates every identifier; raw pools are excluded from the sandbox; SQL is never assembled from strings an agent wrote.

FAFO Core Function ForgePostgreSQL system catalogsRust data layer for AI-written code
The sandbox boundary

Shapes read from the catalogs

FAFO Core and Function Forge lets functions, including ones written by AI agents, run against any registered data source, and I wanted that with no table name in code and no route to SQL injection. The substrate reads the shape of a view or table from PostgreSQL's system catalogs at runtime and caches it, including vector dimensions from each column's type modifier and array element types, so a function is written against a contract. JSON values are checked against the discovered column types, and binding follows the column type.

embedding · vectorscore · integertags · array
Values that fit · bound
Values that do not · refused
A short vector leaves its slot unfilled; text arriving for an integer does not fit the slot at all.

One entry point for identifiers

Dynamic SQL needs dynamic identifiers, which is where injection usually gets in. In this substrate an identifier has one entry point.

One statement
SELECT … FROM"orders"WHERE id =$1
parameters, sent apart from the text
Identifiers at the resolver
A plain table namequoted into the statement
A name carrying a second statementfails the pattern
the pattern check

Raw connection pools are left out of the prelude that function code imports, so a function has no way around the resolver.

A bounded context for AI-written code

That boundary is what makes Function Forge safe to hand to an agent. A generated function's developer zone gets a capability-bounded context object. See Tools that build tools, under governance.

From a generated function's developer zone
Readthrough the schema resolver
Writethrough the governed write path
Open a raw connection poolnot in the prelude
Anything the context lacksa request to extend the framework
the context object
No one has to catch a stray query; the code has no way to write one.

I treat SQL injection and schema coupling as API-design problems and solve them by limiting what code can reach.

That is what made it reasonable to let agents write processing code against real data. PostgreSQL is the database; the resolver, the type-directed binding and the sandbox boundary are mine.