- jarvis (00-story): 6th track, 2nd software built with writeonce — an AI assistant; direct-HTTPS design; blockers named (net.connect + TLS) - runtime-v2 7 observability + 8 symmetric cipher: moved from the language track (were 30/43); 9 in-process TLS: created from the gap jarvis surfaces, RETIRES the "TLS is the proxy's job" doctrine (both directions) - language 41 (arena hang): fix design to ready — marshal cross-shard messages (root), align the shard_id % nshards route/compare + assert bound; poison-on-free + minimal fixture as follow-ups - fiber scope-gap analysis (plan/exploration/fiber/01): porch vs fiber, what porch lacks, would developers prefer porch - board + dependency-graph synced (porch 2-8 ready; rv2 table; §5/§5a graphs) (cherry picked from commit 203470ceb2a151fe3584931cd4237af3f96a9f29)
88 lines
5 KiB
Markdown
88 lines
5 KiB
Markdown
# Story — `porch`, the writeonce web framework
|
||
|
||
The second track. Where
|
||
[`language-runtime-database/`](../language-runtime-database/00-story.md) grows
|
||
the *language*, this track grows the one library written **in** it:
|
||
[`porch`](../../examples/porch/README.md), consumed by every serving sample
|
||
through `wo.toml [deps]`.
|
||
|
||
Numbering restarts at 1 and is local to this track. Frontmatter carries
|
||
`track: porch` so a query over `docs/stories/` can tell a porch iteration 3 from
|
||
a language iteration 3. Status rules are the repo's, unchanged: `status:` in
|
||
frontmatter is the only place state lives, no directory encodes it.
|
||
|
||
## Why a separate track
|
||
|
||
Three reasons, all practical:
|
||
|
||
1. **Different substrate, different gates.** porch is `.wo` source. Its
|
||
iterations are proven by `just web-app` and `just site`, never by the
|
||
conformance corpus or `oop-accept`. Mixing them into the language track's
|
||
sequence made both harder to read.
|
||
2. **Different cadence.** A porch slice is days; a language slice that touches
|
||
`wob.h` and the VM is longer and riskier. Interleaving them in one numbering
|
||
forced false ordering decisions.
|
||
3. **The framework is now the product surface.** `writeonce.de` is served by
|
||
porch. Its gaps are what a visitor hits first, so they deserve a roadmap that
|
||
is not buried behind runtime work.
|
||
|
||
The language track stays upstream: when a porch iteration needs a new builtin,
|
||
that half is called out explicitly and the language track owns it.
|
||
|
||
## Where the sequence came from
|
||
|
||
The [Fiber v3.5.0 parity study](../../plan/exploration/fiber/00-fiber-parity.md)
|
||
— gofiber/fiber read end to end against porch's actual `.wo` source: its routing
|
||
surface, `Req`/`Res` API, binder, lifecycle hooks and the `Config` of all 32 of
|
||
its `middleware/` packages. Nine of those 32 already have a working porch
|
||
counterpart, so this is a breadth roadmap, not a rescue.
|
||
|
||
That study replaced language-track
|
||
[iteration 39](../language-runtime-database/39-web-framework-parity.md), which is
|
||
now a pointer here.
|
||
|
||
## The sequence
|
||
|
||
Ordered by dependency, not by importance — and the first slice is deliberately
|
||
the *cheapest*, so the store pattern and the gate shape are proven before the
|
||
risky work starts.
|
||
|
||
| # | Iteration | Delivers | Needs |
|
||
| --- | --- | --- | --- |
|
||
| 1 | [Store-backed middleware](01-store-backed-middleware.md) | rate limiting + idempotency over a `@table` store, serialized through a sharded actor pool | 🔄 in progress; needs no new primitive (`call`/`send`/`monitor`/`time.after` all landed) |
|
||
| 2 | [Randomness and cookies](02-randomness-and-cookies.md) | a `random_bytes` runtime builtin, repeated response headers, `Cookie:` parsing, signed cookies | a language-track builtin (phase A) |
|
||
| 3 | [Sessions](03-sessions.md) | server-side sessions, idle + absolute timeout, revocation | 2 |
|
||
| 4 | [CSRF](04-csrf.md) | token mint/verify, trusted origins, single-use tokens | 2, 3 |
|
||
| 5 | [Routing and response ergonomics](05-routing-response-ergonomics.md) | the remaining method helpers, named routes, per-route body limit, request ids, the missing response helpers | nothing — parallel to 2–4 |
|
||
| 6 | [Streaming core](06-streaming-core.md) | incremental response writes and chunked framing — the seam three iterations wait on | nothing new, but it changes `Resp` |
|
||
| 7 | [SSE and compression](07-sse-and-compression.md) | server-sent events, gzip/deflate | 6 |
|
||
| 8 | [Static files and lifecycle](08-static-and-lifecycle.md) | byte ranges, cache headers, directory listing, lifecycle hooks, the small middleware everyone ships | 6 |
|
||
|
||
```
|
||
1 ─ independent, start here
|
||
5 ─ independent, any time
|
||
2 ──▶ 3 ──▶ 4
|
||
6 ──▶ 7
|
||
└──▶ 8
|
||
```
|
||
|
||
## What this track does NOT own
|
||
|
||
| Not porch's | Owner |
|
||
| --- | --- |
|
||
| typed binding of query/params/form into a class | language: [`@derive`](../language-runtime-database/29-compile-time-metaprogramming.md) — reflection is forbidden by principle 13 |
|
||
| TTL cache, `transaction { }`, durable job queue | language: [iteration 18](../language-runtime-database/18-memory-db-features.md) |
|
||
| a `proxy` middleware | language: [iteration 38](../language-runtime-database/38-content-platform-capabilities.md) — needs `net.connect`, which does not exist |
|
||
| metrics, profiling, per-change CI, fuzzing | [runtime-v2 7](../runtime-v2/07-observability.md) — observability (was language iteration 30; metrics/profiling/trace-on-trap; CI + fuzz are tooling, split out) |
|
||
| TLS, HTTP/2 | nobody — proxy-terminated by doctrine |
|
||
| a runtime template engine | nobody — rejected; markup is a compile-time literal (`writeonce-view`) |
|
||
| a radix-tree router | nobody yet — waiting on a *measurement*, not a decision |
|
||
|
||
## Review protocol
|
||
|
||
Same as the language track: the developer reads one iteration, approves or
|
||
amends; the next starts only after approval. Each iteration is an unsplittable
|
||
value slice with phases, per-phase tasks, Given/When/Then acceptance criteria,
|
||
and an out-of-scope list. Every phase ends with both serving gates green —
|
||
`just web-app` and `just site` — because porch has two consumers and a change
|
||
that only satisfies one is not done.
|