TESTING / DEVELOPMENTapi-completion-roadmap.md
Status dokumen bukan klaim bahwa fiturnya sudah tersedia.

RFC dan proposal mencatat rancangan. Untuk kemampuan yang benar-benar dapat dipakai, lihat matriks kapabilitas runtime dan catatan rilis.

YAZA API Completion Plan

Purpose and completion rule

API work is the first product priority. Web, monolith, and mobile work starts after the API release gates below are met. “100% complete” means complete against a published, versioned API profile and its acceptance tests; it cannot mean that every possible framework feature or future database has been implemented. New capabilities must enter through a reviewed specification and a compatibility plan.

This is a living delivery plan. It records current gaps and defines observable evidence for calling a release profile complete. It does not claim that planned work already exists.

Progress snapshot — 2026-10-28

Estimated API profile completion: about 50%. This is a manual planning estimate against Gates A–F, not a CI-derived score or a claim of production readiness. Core CRUD, the first-party PostgreSQL path, substantial request validation, and API documentation generation work; every release gate still has material exit criteria open. The server now combines nonblocking socket readiness with a bounded worker pool for generated controller handlers and database-backed readiness probes. Handler functions and PostgreSQL operations are still blocking calls within worker threads. Source-level async/await and a multi-worker cooperative scheduler remain unimplemented.

2026-10-28 keep-alive latency fix: The event loop could sleep for its 100 ms fallback interval after the scheduler had already parsed a keep-alive request. It now uses a zero-time readiness pass whenever a connection has a request ready for dispatch. In two YAZA-only local macOS/arm64 runs of 1,000 requests at concurrency 32 with keep-alive enabled, /healthz improved from about 104.6–106.7 ms p50 and 401–504 requests/s to 2.05–2.07 ms p50 and 15,179–15,305 requests/s. /api/response remained at about 2.53–2.62 ms p50. These are focused local regression measurements, not a refreshed cross-language benchmark or a production performance claim. The API HTTP smoke and native ASan/UBSan runtime suite pass after the fix.

Language and API sequencing

The API remains the first product release priority; do not block it on implementing every planned general-purpose language feature. Keep a versioned, tested YAZA core profile and implement language/runtime capabilities as API release-gate dependencies require them. Each such capability must also have pure-language examples and conformance coverage. In particular, memory ownership and source-level asynchronous tasks/cancellation must be treated as core prerequisites for the API's corresponding safety and concurrency guarantees. Production web, monolith, and mobile releases remain behind the API release gates.

API concurrency priority

Asynchronous execution and multi-threading are first-class API priorities within the API release, not deferred language or mobile work. A bounded worker pool now executes generated controller/service/repository handlers and database-backed readiness probes away from the event loop. Socket registration, response framing, response writes, health, and metrics remain event-loop-owned. Calls are synchronous within each worker; the generated language does not yet expose async/await. Describe this as concurrent API handler execution, not as a language-level async scheduler.

Implement concurrency in this safety-first order:

  1. Make request execution isolated. Replace ambient mutable HTTP request/response globals with an explicit request execution context; make allocation arenas thread-local or explicitly owned; classify shared counters, rate-limit state, caches, and database-pool state as synchronized or event-loop-owned. Keep socket descriptors, connection buffers, and response writes owned by the event loop.
  2. Harden the bounded API worker pool. The pool runs generated controller handlers and database-backed readiness probes with 1–32 fixed threads, owned completion results, and a kqueue/epoll wakeup. YAZA_API_MAX_IN_FLIGHT independently bounds queued, active, and completed-but-undelivered jobs; it defaults to connection capacity and saturation returns a safe HTTP 503. A loopback concurrency harness now fills this limit, checks the rejected-job metric, and confirms health remains responsive. Workers do not own or write client sockets. http_request_cancelled() -> Boolean exposes the job flag for loops that poll cooperatively; PostgreSQL pool acquisition and native TCP/TLS readiness waits check that flag in bounded intervals of at most 50 ms. These remain blocking calls inside worker threads, and synchronous DNS resolution is not cancellable. There are no automatic compiler safepoints, and blocking/native calls are not forcibly interrupted. Shutdown now exits within its configured deadline without freeing state still referenced by a worker; the noncooperative case ends with process failure. PostgreSQL-backed query overlap/load evidence and Linux runtime evidence remain open.
  3. Expose structured async to YAZA handlers. Add typed Task[T]/Result[T,E], async/await, request-scoped child tasks, cancellation propagation, deadlines, and cleanup rules. A request cannot finish while its children still reference request memory or a database lease.
  4. Make network I/O suspendable and then scale workers. Convert YAZA PostgreSQL and outbound HTTP socket waits to readiness-driven state machines; use the blocking pool only for operations that cannot be made nonblocking. Add multiple scheduler workers/work stealing only after single-worker semantics, ownership, cancellation, race instrumentation, and bounded-memory behavior are proven.
  5. Prove the API behavior under load. Exercise slow database/handler work while health and unrelated routes continue responding; verify overload, cancellation, deadlines, shutdown, task/queue/connection bounds, and database lease cleanup. Compare c=1/8/32 with the existing workload and publish latency percentiles, throughput, RSS, startup time, and failure counts before changing performance claims.

The required isolation refactor is partially in place: active request context and allocation arena selection are thread-local, program-arena accounting and in-memory records are synchronized, and native network handles use per-socket locks. HTTP jobs own copied request state and results return through the event loop. The new pool has ASan/UBSan and ThreadSanitizer integration evidence; PostgreSQL-backed overlap still needs live database testing.

Current baseline

  • The native YAZA CLI and compiler can generate, check, test, and run API projects.
  • API compilation now expands the reachable application modules once for route-shape analysis and reuses that source through checking, API generation, OpenAPI generation, and layer binding checks. It also indexes eligible function return signatures once instead of rescanning the full expanded source for each route. This fixes the API-check path that previously exhausted the compiler's bounded 512 MiB arena; it does not yet make compilation incremental or reduce memory for every compiler command.
  • The API runtime has HTTP/1 request parsing, routing metadata, typed path/query/header access, scalar and nested-shape JSON body binding, TextList, primitive typed arrays (List[Number], List[Int32], List[Float64], List[Boolean], List[Text]), declared-shape arrays, nullable Option[List[T]], and bounded list validation. API arrays are capped at 64 elements; request decoding, shape response serialization, OpenAPI, and Postman preserve element types. Other implemented pieces include a Product CRUD study case, health/readiness endpoints, Prometheus HTTP status and active/limit connection metrics plus PostgreSQL pool gauges (with no-database and PostgreSQL-backed smoke coverage), access logs, basic shared-token authentication, CORS, and Postman/OpenAPI generation. yaza new --api creates the layered Product Catalog study case; yaza new --minimal-api creates a one-file route starter. Broader route examples live in a test fixture. yaza generate writes the Postman collection, OpenAPI 3.1, and Swagger-compatible document together under docs/api/; individual --postman, --openapi, or --swagger flags select one output. Postman writes a full absolute URL for every operation. Scalar request bodies can generate documentation examples from their declared field types; example json customizes them, and actual request data always comes from the client. Every response carries a 128-bit OS-random X-Request-ID; the same ID appears in the structured access event, and CORS exposes it to browser clients. This is request correlation, not distributed tracing.
  • Every GET route now also supports HEAD with inherited route policies, GET-equivalent representation headers, and no transmitted response body. Built-in health/readiness/metrics routes support it too; Allow lists include HEAD, and OpenAPI/Postman generators emit bodyless HEAD operations/requests. Raw TCP HTTP smoke checks verify that no body bytes follow the headers, and generation smoke checks both outputs. The complete HTTP smoke passes normally and under ASan/UBSan on macOS; Linux and maximum header-size boundaries remain unverified.
  • Routes may declare auth required, auth public, or auth jwt; omitted policy keeps the configured global bearer behavior. auth jwt verifies a bounded compact HS256 token against YAZA_JWT_SECRET, exact YAZA_JWT_ISSUER and YAZA_JWT_AUDIENCE, and the exp/optional nbf/iat claims. A matching authenticated handler can read verified top-level string claims with http_auth_claim_text(name) -> Option[Text]; the accessor is unavailable to public/shared-Bearer handlers, values are capped at 1023 UTF-8 bytes, and the request-scoped decoded payload is wiped after dispatch. JWT-only non-loopback mode requires at least one JWT route and an explicit auth policy on every route. OpenAPI and Postman emit Bearer metadata for JWT routes, and OpenAPI adds x-yaza-authentication: jwt-hs256. Token issuance, typed principals, centralized roles/permissions, sessions, and ownership-aware authorization remain incomplete.
  • Shared Bearer authentication now accepts an optional second distinct credential through YAZA_API_TOKEN_SECONDARY; each valid token is independently length/character-checked and every request compares both fixed-width candidates. This enables a staged rolling rotation, documented in the generated API starter. Central revocation, per-user tokens, deployment-manager integration, and Linux end-to-end evidence remain open.
  • Routes can declare success status 200, 201, 202, or 204; the compiler carries it into runtime metadata and OpenAPI, and 204 responses omit the body and content headers. The API status fixture verifies both handler and controller routes during bootstrap.
  • Route files support nested indentation-scoped group "/prefix" [auth required|auth public|auth jwt] [rate_limit REQUESTS per WINDOW_MS] [cors "https://origin"]: blocks. Static prefixes are normalized and expanded before route validation, runtime generation, OpenAPI, and Postman; grouped "/" routes resolve to the group base URL. Group auth, rate-limit, and exact-origin CORS policies inherit into nested groups, and a route-level declaration overrides its inherited policy. Each rate policy is an IPv4-client token bucket with independent group scope; the optional global limiter remains available. OpenAPI exposes the effective request/window values as x-yaza-rateLimit and route origin as x-yaza-corsOrigin. A general user-defined middleware chain, distributed quotas, multi-origin lists, and actor-aware policies remain incomplete.
  • Nested API request shapes can declare validate email email for Text or Option[Text] fields. The bounded ASCII syntax check returns invalid_email with a safe field path and emits OpenAPI format: email; it does not verify mailbox ownership or accept internationalized addresses.
  • Nested API request shapes can also declare an anchored validate <field> pattern "^...$" rule. It supports a bounded ASCII subset with literals, classes/ranges/negation, punctuation escapes, and ?, *, +; groups, alternation, Unicode patterns, and backtracking constructs are rejected. Matching is capped at 128 pattern bytes, 64 atoms, and 1023 input bytes, emits a JSON Schema pattern, and returns the fixed pattern validation code. Regex unit and invalid-compiler-fixture checks, OpenAPI/Postman generation, and HTTP smoke passed normally and with ASan/UBSan.
  • Separate YAZA controller, service, repository, model, contract, and interface files exist. All six generated Product CRUD routes execute YAZA controller → service → repository functions. Product create, replace, patch, and find return Result[ProductRecord, ApiError] and strictly decode stored JSON into the declared shape; list returns Result[List[ProductRecord], ApiError] with typed JSON-array decoding, HTTP serialization, and an OpenAPI array item schema; delete returns a typed ProductDeleteOutcome but keeps its bodyless 204 response. With DATABASE_URL, the repository uses the YAZA PostgreSQL adapter; without it, the repository calls std/api/memory_records.yz, whose bounded native adapter mutates the server's in-memory resource table and returns Result values. The adapter no longer constructs or sends HTTP responses; the normal handler response path serializes repository outcomes. yaza check verifies layer/interface metadata names and signatures, then requires each service/repository method to bind uniquely to a reachable function in its matching implementation file with exactly matching parameter count/types and return type. Product list pagination passes typed limit and offset through each layer; starter CRUD and full no-database HTTP fixture smokes verify CRUD, typed Product lookup, and chunked JSON creation. Negative conformance checks cover absent/duplicate bindings, unknown targets, arity/type/return mismatches, wrong repository delegation, and controller actions calling the wrong service method. These remain compile-time static bindings; runtime-polymorphic interface dispatch, and general persistent/in-memory YAZA data structures remain incomplete.
  • Generated Product CRUD, startup/schema checks, and /readyz now use the pure-YAZA PostgreSQL v3 client. API startup and readyz hooks are declared in src/main.yz, compile-checked as reachable zero-argument Number and Boolean functions, and invoked by the native server lifecycle. Startup configures bounded server-side timeouts, verifies the migrated API-record table, and seeds the sample rows idempotently; readiness checks out a bounded-budget connection through the YAZA pool and checks the table with a 500 ms per-operation budget. Generated API builds have no libpq link dependency, verified by macOS dependency/symbol inspection. The full database-configured HTTP smoke passes against a disposable PostgreSQL 18.6 container after migration, covering startup, seeding, /readyz, CRUD, restart persistence, a paused-database readiness failure/recovery cycle, a forced PostgreSQL process loss during an active create, and readiness recovery after PostgreSQL restarts. Readiness returned PostgreSQL-specific 503 in about 500 ms while paused and returned 200 after resume; the active create returned a safe 503 with Retry-After. The smoke holds PostgreSQL's published loopback host port fixed across container restart and verifies that the same API process returns readiness 200 after PostgreSQL restarts. It does not retry the failed create, which correctly returns 503 when its connection is lost. Product CRUD and lifecycle operations now check out connections from the bounded process-local YAZA pool. The pool has a default per-database size of 8, a 5,000 ms acquisition budget, a 60,000 ms idle timeout, hard caps of 64 per identity and 128 process-wide, health checks for reused idle handles, and shutdown draining. Its coordination primitives are thread-safe; generated API handlers and database-backed readiness now execute on the bounded worker pool, while the event loop owns sockets and response writes. Two simultaneously blocked handlers, health/readiness isolation, 504 timeout accounting, and shutdown pass normal, ASan/UBSan, and ThreadSanitizer loopback checks. Live PostgreSQL overlap and load/saturation behavior are not yet established. Remote TLS and broader server matrix remain unverified.
  • std/pg/api_records.yz implements bounded, parameterized JSONB probe/list/get/insert/replace/patch/delete operations. Language tests and a strict fake PostgreSQL protocol fixture pass in normal and ASan/UBSan builds. The generated Product repository calls list/get/create/replace/patch/delete through this adapter when PostgreSQL is configured. It maps PostgreSQL SQLSTATE unique violations to AlreadyExists, other constraint violations to Conflict, and query cancellation/timeouts to Timeout; infrastructure and unclassified failures remain safe Unavailable responses. The disposable PostgreSQL 18.6 HTTP smoke injects live SQLSTATE 23505, 23514, and 57014 errors and verifies 409 already_exists, 409 conflict, and 504 timeout, with server error details absent. It also terminates PostgreSQL during an active create and verifies a safe 503 unavailable. Automatic request retry/reconnection after the database process restarts and additional SQLSTATE classes remain unverified.
  • The socket event loop is single-threaded and owns I/O; generated handlers and database-backed readiness run on the bounded worker pool. macOS kqueue is exercised; the Linux epoll backend is source-only. The template maps every declared ApiError case, validated InvalidInput(field: Text), and bounded safe ValidationFailed(errors: TextList) paths to fixed responses. Direct Shape, Option[Shape], and Result[Shape, ApiError] results serialize nested scalar and TextList fields, and OpenAPI derives success schemas from those shapes. The runtime response writer normalizes legacy JSON error strings to the shared nested error.type/error.code envelope, including authentication and generic HTTP status errors. OpenAPI lists common status envelopes on every operation. A shared typed error model and typed framework/authentication/database conversion remain incomplete. TLS for inbound HTTP, general middleware composition, role-based/object authorization, trusted-proxy identity, distributed quotas, and ownership-driven transaction cleanup for arbitrary service/repository scopes remain incomplete; PostgreSQL pool and worker state are exposed through /metrics; controller/database calls remain blocking within pool workers. Migrations use explicit lexical cleanup guards.
  • OWASP Top 10:2025 mapping and the separate OWASP API Security Top 10:2023 mapping map current controls, evidence, and gaps; the 2021 mapping remains historical. These improve traceability; they do not close API security release gates or claim production readiness.
  • Optional per-client IPv4 token buckets can apply globally through YAZA_RATE_LIMIT_REQUESTS/YAZA_RATE_LIMIT_WINDOW_MS or to a route/group through rate_limit REQUESTS per WINDOW_MS. The fixed 1,024-entry table keys route policies by client and policy scope, returns 429 with computed Retry-After, and fails closed when full. Normal and ASan/UBSan unit tests plus a nested-group HTTP/OpenAPI smoke cover the behavior. The policies are process-local and IPv4-only; distributed quotas and arbitrary middleware composition remain open.
  • SIGINT/SIGTERM now stops accepts, makes a zero-time readiness pass after an interrupted poll, finishes requests already readable on accepted sockets, sends Connection: close, and then closes incomplete/idle sockets. A fragmented-request HTTP smoke verifies the response and clean exit in normal and ASan/UBSan runs. This drains queued HTTP response bytes and cancels queued and running worker jobs. Worker shutdown uses the same configured grace deadline; if a handler remains active, YAZA exits with failure instead of freeing runtime state while that worker is still using it.
  • Non-PostgreSQL driver engines are not implemented. See Database driver architecture.
  • The provider-neutral std/db/core.yz contract now has tagged SQL values, explicit SQL NULL, checked typed accessors, stable error codes, and conservative capability descriptors. std/db/postgres.yz converts these values to separately bound PostgreSQL parameters with explicit OIDs for NULL and decodes known PostgreSQL integer, Boolean, finite Float64, text, and bytea scalar columns into DbValue; unknown or unsupported OIDs fail explicitly. std/db/query.yz models a bounded SELECT projection, a single typed comparison, ordering, and pagination; its PostgreSQL lowering quotes validated identifiers and binds values separately. The PostgreSQL 18 container smoke now executes this descriptor against a temporary table, checks decoded rows and paging, and confirms injection-shaped data remains a value. The descriptor is not yet the compiler's native query-block syntax and does not resolve identifiers against schema snapshots. Provider-neutral connection/transaction lifecycles and pooling, typed row-shape mapping, and non-PostgreSQL engines remain absent; the PostgreSQL API uses a separate bounded process-local pool.

2026-10-27 request DTO vertical slice: The Product controller assembles validated path/body values into a shared ProductInput, then passes it to service and repository functions. List pagination remains explicit. The repository no longer reads ambient HTTP request or response state; DELETE 204 is route metadata. Compiler conformance requires the DTO signatures for create/replace/patch/find/delete and verifies implementation signatures. This covers the generated Product case only, not general DTO generation or a complete API contract.

2026-10-27 integer request validation vertical slice: validate <field> integer now constrains Float64 fields during nested API body decoding to exact whole values in [-9007199254740991, 9007199254740991], the IEEE-754 safe integer interval. The decoder inspects the JSON decimal spelling before Float64 rounding; fractions and out-of-range values return safe field-scoped 422 responses before controller execution, while nullable/omitted fields skip the constraint. OpenAPI marks the field as integer and reports identical bounds, and the 422 schema includes the integer code. The complete API generation and HTTP smokes pass normally and with ASan/UBSan. This does not add language-level Int64 or make every API field schema-driven.

2026-10-27 OpenAPI numeric alignment vertical slice: Number API parameters and shape fields now generate signed 64-bit integer schemas, Int32 generates bounded 32-bit integer schemas, and Float64 remains a number. The generator composes intrinsic ranges and declared validation constraints with allOf. Response, path, query, and nested-body schema assertions pass; the full three-stage native bootstrap passed with 39/39 language tests and normal plus ASan/UBSan API HTTP smokes.

2026-10-27 bounded validation-error response slice: The runtime now allocates enough bounded space for all 64 documented validation field paths at 128 bytes each. The API smoke verifies the largest valid response is preserved in both normal and ASan/UBSan runs; unsafe paths still collapse to the safe fallback envelope.

2026-10-27 typed request-array slice: Nested request shapes now accept bounded List[DeclaredShape] arrays and nullable Option[List[DeclaredShape]] arrays, decode and validate each object before controller dispatch, and enforce declared item bounds. OpenAPI and Postman include the nested item schema and declared example. The fixture's normal/sanitized HTTP smoke, generation smoke, 42/42 language suite, and full macOS bootstrap pass. Primitive List[T] request fields beyond TextList remain outside this slice.

Release gates

Gate A — Executable layered CRUD

  • Each generated CRUD operation dispatches through controller → service interface → service implementation → repository interface → repository implementation.
  • The generated sample includes list, get, create, replace/update, partial update, and delete semantics with stable status codes and typed request/response shapes.
  • In-memory storage and PostgreSQL storage implement the same repository contract.
  • Validation, not-found, conflict, and persistence failures use a stable typed error model; responses never leak secrets or raw SQL errors.
  • Interface conformance is checked by the compiler and runtime routing invokes the implementation rather than using special Product-specific generic behavior.

Gate B — PostgreSQL is first-party and verifiable

  • The API uses the pure-YAZA PostgreSQL implementation selected by the project owner; no libpq dependency is required for generated API builds.
  • Verified TLS, SCRAM-SHA-256, parameter binding, typed scalar codecs, row decoding, transactions, timeout/cancellation, and connection cleanup work together.
  • A live PostgreSQL service is part of repeatable CI. Migration, CRUD, and restart persistence passed manually against PostgreSQL 17.6; the current lifecycle hooks plus full database-configured HTTP smoke passed against PostgreSQL 18.6, including readiness pause/resume, same-process readiness recovery after PostgreSQL process restart, live SQLSTATE mapping, and a safe 503 when PostgreSQL is terminated during an active create. CI must repeat supported-version coverage and add rollback, active-query timeout, invalid credentials, remote certificate validation, and broader server-version coverage. Automatic retry of an interrupted write is not expected without an explicit idempotency contract.
  • Schema snapshots and migration checks are generated and consumed consistently by CLI and API builds.

Gate C — Stable API contracts and errors

  • One versioned contract model drives route registration, runtime validation, OpenAPI, and Postman output.
  • Contracts support documented path/query/header/body parameters, required/optional values, nested objects, supported collection/variant fields, response shapes, status codes, and error schemas.
  • Unknown input, malformed JSON, validation errors, authentication failures, not-found, conflicts, timeouts, and database failures have stable codes and safe field paths.
  • Generated OpenAPI is validated against its declared version and compared to runtime behavior in integration checks.

Gate D — Security and operational behavior

  • A composable middleware pipeline supports request IDs, safe logging, authentication/authorization, CORS, request limits, deadlines, and centralized error conversion. Request ID generation, response headers, access-log correlation, and CORS exposure are implemented in the shared HTTP response path; the pipeline and remaining policies are still incomplete.
  • Non-loopback IPv4 binds fail closed unless YAZA_API_TOKEN is set, or JWT-only mode has at least one auth jwt route and every declared route has an explicit policy. Static bearer comparisons and JWT signature checks are constant-time for their fixed comparison widths; duplicate Authorization headers are rejected. Routes support auth required, auth public, and auth jwt, reflected in runtime enforcement, OpenAPI, and Postman. JWT uses HS256 only, pins issuer/audience, and validates expiration. Gate D still requires a composable middleware pipeline, login/token issuance, users/roles and actor-aware authorization, central shared-token revocation, JWT signing-key rotation, TLS, secret lifecycle controls, and consistent safe error conversion.
  • HTTP server behavior is tested under malformed framing, slow clients, shutdown, overload, cancellation, and concurrency. TLS terminates at YAZA or an explicitly documented trusted proxy boundary.
  • The release profile includes actual concurrent controller/service/repository execution: a slow handler or database operation cannot block health checks or unrelated requests; fixed worker/queue limits, overload behavior, cancellation/deadline cleanup, and bounded shutdown are verified. Socket readiness alone does not satisfy this item.
  • Health, readiness, metrics, and structured logs have stable schemas and bounded memory/output behavior.
  • Security checks, sanitizer runs, fuzz regression tests, and a dependency/license review pass on supported targets.

Gate E — Database portability

  • std.db defines provider-neutral connection, transaction, typed parameter, row, error, cancellation, and capability contracts without pretending that SQL and key-value/document databases are identical.
  • PostgreSQL is first. Each additional provider is released only when its conformance suite, security review, operational notes, and supported-version matrix pass.
  • The initial expansion order is PostgreSQL, SQLite, MySQL/MariaDB, then SQL Server; Redis is a separate key-value contract. Oracle and document stores follow only after protocol/legal review and a justified demand profile.
  • Applications can select a provider through explicit project configuration. Unsupported provider features fail clearly instead of silently degrading.

Gate F — Developer workflow and release evidence

  • yaza new --api, check, build, run, test, generate --openapi, generate --swagger, generate --postman, migrations, database inspection, and security audit work from a clean installation.
  • API integration tests can start and tear down supported database services without manual state or leaked credentials.
  • Documentation includes a new-user tutorial, deployment/security guide, route and database reference, troubleshooting, and compatibility policy.
  • Each release publishes the tested operating systems/architectures, limitations, checksums, and reproducible release notes.

Delivery order

  1. Make Product CRUD truly execute through the declared YAZA layers, first with an in-memory repository.
  2. Extract a provider-neutral database contract and keep all generated PostgreSQL API access on the pure-YAZA client. The API no longer links libpq; continue hardening and validating the full path.
  3. Complete live PostgreSQL TLS/auth/query/transaction integration and CI evidence.
  4. Unify contracts, response schemas, status codes, errors, Postman, and OpenAPI around one metadata source.
  5. Complete the API concurrency priority track above: request-state isolation, bounded workers, structured async handlers and cancellation, database/network wait integration, then verified multi-worker scheduling.
  6. Finish middleware, configuration/secrets, authz, operational limits, and graceful draining, integrating them with async request lifetimes.
  7. Add SQLite, then MySQL/MariaDB and SQL Server engines under conformance gates; add key-value/document contracts separately.
  8. Complete Linux runtime CI, fuzzing, sanitizer, load, fault-injection, and release documentation.
  9. Keep the API release gates first. A low-risk YAZA UI web-starter foundation may advance in parallel, but production web applications, monolith, and mobile releases remain behind the API gates.

Progress ledger

Workstream Current status Exit evidence
Product request DTO flow Implemented slice Verified controller binding into ProductInput, explicit service/repository parameters, repository HTTP-state isolation, route-declared DELETE 204, and compiler signature conformance. The 2026-10-27 macOS bootstrap passed three self-host stages with byte-identical generated C, 39/39 language tests, API layer/generation checks, and normal plus ASan/UBSan HTTP smokes. General DTO generation and typed response models remain open.
Numeric request validation Implemented slice Nested Float64 request fields support validate <field> integer; runtime checks finite whole-valued input within signed Int64 bounds, returns safe field errors for fractions/out-of-range values, and skips omitted/null optionals. OpenAPI emits the same integer type and range. Normal and ASan/UBSan HTTP smoke and OpenAPI/Postman generation smoke pass. General schema-derived scalar types remain open.
Generated API CLI workflow Partial Clean-install end-to-end run on every supported host
Typed route-handler outcomes Partial Handlers accept Text, Option[Text], direct/nested Shape, Option[Shape], List[Shape]/Option[List[Shape]], Result[Text, E], Result[Shape, E], and Result[List[T], E]/Option[List[T]] for scalar elements Number, Int32, Float64, Boolean, and Text; none maps to 404. Typed lists are serialized with declared element checks and bounded JSON output, and OpenAPI derives each array item schema. Shape fields also serialize TextList, primitive List[T], and declared-shape lists; request shapes decode primitive arrays and declared-shape arrays, with nullable Option[List[T]], a 64-item cap, and bounds validation. Result[..., ApiError] maps declared cases to fixed status/code envelopes; bounded validation field paths are checked before inclusion. The runtime normalizes legacy HTTP errors to the common nested JSON envelope, and OpenAPI lists common error responses on every operation. Arbitrary nested collection codecs, a shared typed response/error model, and typed framework/authentication/database conversion remain incomplete.
Layered Product CRUD Partial vertical slice; release gate incomplete All six routes execute YAZA controller → service → repository functions; create, replace, patch, and find return Result[ProductRecord, ApiError] after strict JSON-to-shape decoding, while list returns Result[List[ProductRecord], ApiError] with typed JSON-array decoding, HTTP serialization, and OpenAPI array items; delete returns a typed ProductDeleteOutcome but keeps its bodyless 204 response. Configured CRUD uses the YAZA PostgreSQL adapter, while the no-database repository calls std/api/memory_records.yz and returns results through normal handler serialization. The bounded demo table is still native runtime storage. Metadata interfaces receive exact one-to-one signature checks and negative smoke coverage. Starter CRUD, complete no-database HTTP fixture, typed read/write/list generation and HTTP checks plus bodyless delete checks, and historical PostgreSQL 17.6 CRUD/restart evidence pass. Exit evidence still requires runtime-polymorphic interface dispatch, general YAZA-owned storage, wider live-server coverage, and unified HTTP response/error contracts
PostgreSQL API provider Partial integration Generated Product CRUD, startup/schema verification, and /readyz use std/pg and std/pg/api_records.yz; API binaries build without libpq. The current migration plus full database-configured HTTP smoke passed against disposable PostgreSQL 18.6, including lifecycle startup, sample seeding, readiness pause/resume, CRUD, restart persistence, live SQLSTATE-to-HTTP mapping, a safe 503 with Retry-After for PostgreSQL termination during an active create, and /readyz recovery from the same API process after PostgreSQL restarted on the same published host port. PostgreSQL 17.6 CRUD/restart evidence also exists for the earlier lifecycle implementation. The integrated bounded process-local pool has C-harness coverage and passed the PostgreSQL 18.6 API smoke. Remote TLS, broader PostgreSQL versions, automated database-container CI, and Linux API verification remain required; automatic retry of an interrupted write requires a separate idempotency contract and is not part of this proof.
Structured database query API Partial std/db/query.yz defines a bounded SELECT descriptor with validated projection, up to 16 typed AND predicates, one ordering column, and bounded pagination; PostgreSQL SQL generation binds each non-NULL predicate independently and handles NULL with IS NULL/IS NOT NULL. tests/database_query.test.yz passes as a native executable and under ASan/UBSan, and covers multi-filter SQL, placeholder ordering, the filter limit, NULL behavior, malformed identifiers/values, and error mapping. The complete language suite passes 45/45 in the latest macOS bootstrap. tests/db_postgres_live_smoke.yz now includes two filters and passes yaza check, but that expanded fixture has not yet been executed against a live PostgreSQL service. The native query-block grammar, schema-driven type resolution, OR/grouped predicates, joins, and typed rows remain required.
Native CLI temporary cleanup Implemented slice yaza run and yaza bench remove only YAZA-owned private temporary directories through the bounded openat/no-follow cleanup helper; cleanup failure produces a nonzero result when the program otherwise succeeds. A sanitized yaza run tests/database_query.test.yz completed with exit code 0 and left no new /tmp/yaza-run.* directory, including the Clang program.dSYM directory.
HTTP OPTIONS semantics Implemented slice Ordinary OPTIONS on a registered route returns an empty 204 and path-specific Allow; OPTIONS * returns the server-wide method set; unknown paths stay 404. Allow includes implicit HEAD and OPTIONS. Route-specific auth is preserved by selecting the strictest matching route policy, including JWT-only endpoints. Allowed-origin requests without Access-Control-Request-Method use ordinary OPTIONS; actual CORS preflight continues to validate methods and headers. The complete API HTTP smoke passes normally; the route-auth smoke passes normally and under ASan/UBSan, including rejected anonymous and accepted JWT-only OPTIONS. Linux verification remains open.
Shared API Bearer rotation Implemented slice YAZA_API_TOKEN and optional distinct YAZA_API_TOKEN_SECONDARY are each length/character checked; with both configured, each request checks both fixed-width candidates. Route-auth smoke accepts each credential and rejects secondary-only, short-secondary, and duplicate-token configuration normally and under ASan/UBSan; the full API HTTP CRUD smoke also passes. The dotenv-loader smoke covers loading the secondary variable from .env; a fresh yaza new --api run generated 30 files with the key in .env.example, and the bootstrap now guards that output. The API starter documents rolling rotation. Central revocation, per-user credentials, and Linux verification remain open.
Self-hosted macOS CLI bootstrap Implemented slice The 2026-10-28 bootstrap built three compiler stages from YAZA source, passed the 45/45 language suite, native runtime and sanitizer checks, deterministic mutation fuzzing (10,000 cases), API HTTP and auth smokes, OpenAPI/Postman/Swagger generation, template creation, and CLI run smoke; it produced the updated dist/yaza binary.
API contract generation Partial Runtime, OpenAPI, Postman, response/error schemas derive from the same versioned contract
API security and operational pipeline Partial Public/shared-Bearer/HS256 JWT route policies, exact Host allowlisting, bounded HTTP parsing, rate-limit controls, safe error envelopes, and selected fault tests exist. Shared tokens have a 32-byte minimum, a CSPRNG generator, and two-slot overlap for rolling rotation, covered by local API/CLI smoke. Object/tenant authorization, typed principals, per-user token issuance, central revocation, Linux end-to-end evidence, inbound TLS, async handlers/database cancellation, and release security operations remain open; see the security status and security proposal.
API async and multi-thread execution Partial; bounded handler workers are active; priority Generated controller routes and database-backed readiness probes run on a 1–32 thread pool with per-job deadlines/cancellation flags, owned completion handoff, and event-loop-only socket writes. YAZA_API_MAX_IN_FLIGHT bounds queued, active, and completing jobs independently from open connections; saturation returns 503, increments the rejection counter, and is tested while /healthz remains responsive. The keep-alive dispatch regression improved YAZA /healthz at c=32 from about 105 ms p50 to about 2.06 ms p50 in focused local runs. Remaining: source-level async/await, automatic cancellation safepoints, live PostgreSQL overlap/load, sustained c=1/8/32 benchmarks with RSS/startup/throughput, and Linux end-to-end validation.
Additional database providers Not implemented Provider-specific conformance and release matrix passes
API release profile Not complete Every Gate A–F has recorded evidence

Scope discipline

The API profile is considered complete only at its documented version and target matrix. This plan does not promise unmeasured “fastest” performance. Benchmarks must use identical workloads and configuration, report p50/p95/p99, throughput, RSS, startup time, and binary size, and preserve the exact source/build environment.

2026-10-27 typed list handler update: API handlers now accept direct List[Shape], Option[List[Shape]], and Result[List[Shape], E] values. Direct and present optional lists serialize as JSON arrays; an absent optional list returns 404. OpenAPI derives the matching array item schema and documents the optional 404. The complete API HTTP smoke passed in normal and ASan/UBSan builds; OpenAPI/Postman/Swagger generation smoke passed. Lists of shapes remain a bounded supported case, not general collection serialization for every element type.

2026-10-27 primitive API array update: Request shapes now decode and echo List[Number], List[Int32], List[Float64], List[Boolean], and List[Text], including Option[List[Float64]]; element kinds, integer bounds, finite floats, and min_items/max_items are checked. Shape response serialization, OpenAPI, and Postman generation preserve these array types. Normal and ASan/UBSan API HTTP smoke and OpenAPI/Postman/Swagger generation smoke passed; the macOS bootstrap passed 42/42 language tests. General list-valued handler outcomes and arbitrary collection codecs remain outside this slice.

2026-10-28 structured database query update: SELECT descriptors now compose up to 16 validated predicates with AND, preserving predicate order and binding each non-NULL value to its own PostgreSQL placeholder. NULL equality/inequality compiles to IS NULL/IS NOT NULL without consuming a bind slot; unsupported NULL comparisons fail validation. The focused native query test passes normally and under ASan/UBSan, and the full language suite passes 45/45 in the latest macOS bootstrap. The expanded live-PostgreSQL fixture passes compiler checking; live execution of its new multi-filter path is still pending. OR groups, joins, schema-derived query typing, and typed row mapping remain unimplemented.

2026-10-28 CLI cleanup update: Sanitized yaza run now removes nested compiler artifacts such as Clang's program.dSYM bundle through the bounded, no-follow cleanup helper for private YAZA run directories. A sanitized run of the database-query test exited successfully and left no newly created run directory behind. The benchmark cleanup path uses the same helper but has not had a separate smoke run.

2026-10-28 security review update: Appendix H and the security proposal now include an evidence-labeled source review of the current API/runtime. The Linux epoll listener identity has a source fix and a regression assertion in the native I/O harness; the harness passed locally on macOS, while Linux CI and API end-to-end verification remain pending. API startup enforces a 32-byte minimum shared-token length; the complete HTTP smoke rejects a short token and accepts an exact-boundary test token, and route-auth smoke passes normally and under ASan/UBSan. yaza secret token generates 256-bit OS-CSPRNG secret material and passes its CLI smoke. The check on configured token length does not measure entropy. Per-user token issuance and central revocation, object-level authorization, and inbound TLS remain open; shared-token overlap rotation has local normal and ASan/UBSan evidence. The supplied additions also contained stale reports, including ordinary response writes and the response-header limit, which have been corrected in the risk register. This review is not a penetration test and does not identify a confirmed CVE or reproduced RCE.

2026-10-28 security evidence update: Fuzz builds now make UBSan findings fatal, and tests/fuzz-regression-pipeline.sh proves that a signed-overflow probe terminates. A local macOS deterministic ASan/UBSan run replayed six HTTP/JSON seeds and completed 10,000 mutations. The hosted Ubuntu libFuzzer result and Linux API end-to-end result are still pending. Appendix H.16 and the security proposal now use OWASP Top 10:2025 for general web risks while retaining the API-specific 2023 mapping; neither is a certification. See the security assurance proposal, current OWASP mapping, and Appendix H status.

2026-10-28 API benchmark review: The loopback benchmark reports zero failed requests, but the c=32 YAZA p50 is about 103.5 ms on the 15-byte health route and 105.9 ms on the small JSON route, versus about 0.2–0.3 ms for the fastest measured stacks. The similar delay across health and several JSON sizes rules out response serialization as the sole explanation. The gap widens sharply from c=8 (YAZA p50 0.71 ms) to c=32, consistent with a concurrency/readiness bottleneck in the single-threaded server build measured on 2026-10-28; it is not proof of a specific cause, and the result predates the new worker-pool implementation. The roughly 100 ms latency is close to YAZA_HTTP_POLL_INTERVAL_MS, which is a useful investigation clue but should not be treated as root cause because readiness events should wake the loop early. The separate pure-language benchmark measures fresh CLI process launch through exit and is not evidence about API throughput; it includes startup overhead and YAZA does not lead Go or Nim on those workloads. Next API performance work is to measure accept, socket-read wake, route dispatch, response queue/write, and client completion separately at c=8 and c=32, then fix the measured stage before publishing a new comparison. Both reports are single-machine early comparisons; details and limitations are in the API benchmark report and the pure-language report.

2026-10-28 API concurrency priority: The project owner set asynchronous execution and multi-threading as priorities of the API release. RFC 0005's structured-concurrency model remains the design authority. The delivery order is request-state and memory ownership isolation, a bounded work/completion pool for blocking controller/database work, language-visible structured async tasks and cancellation, nonblocking database/network waits, and only then multi-worker scheduling/work stealing. This records priority and sequencing; it does not claim these capabilities are implemented. API handler/database execution remains synchronous until each slice has source and runtime evidence.

2026-10-28 request-context isolation slice: The native allocator's current arena and ambient HTTP handler request/status fields are now C11 thread-local. Mutations to the shared program arena's allocation list and accounting are protected by a mutex; diagnostics use a locked accounting read. tests/runtime_thread_context.c runs eight threads against isolated HTTP contexts while transferring and freeing shared-arena allocations. It passes as a native macOS build and under ASan/UBSan. This is a concurrency-safety prerequisite only: no API handler or database call has moved off the event-loop thread yet.