908f7ea97389c3dc0a18b20024bb9fd7c640863b
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
df1db790ad |
The URL says which provider set runs, and the seam stops claiming otherwise
The seam arrived carrying a switching design that no longer holds. It presented runtime hot-switching as what shaped it — selection in state, a key on <Refine> to drop the previous backend's cache — and it read the backend from a build global whose comment claimed build.ts defined it. Nothing ever did, and nothing could have: this project serves from src/ in production too, so that define block never reaches what runs. What replaces it is a URL. The default provider set lives at the root, another behind a path prefix naming it, and moving between them is a link. The reload is the mechanism rather than a cost to avoid: it discards the cache and the session with no code to undo them. So the switch helpers are gone and the file is smaller than what it replaced. The resolution is a pure function with its own tests, including the case that is true today — an empty registry, where every URL is the default. The router does NOT yet strip the prefix, deliberately: it is a shared primitive every screen depends on, the suites that would prove a change to it are not run here, and no URL carries a prefix while one backend is registered. That half lands with the second backend, which is what makes it testable. Three claims the move to this base falsified are corrected too. The inbox the count comment points at is local here, not on another branch. The worked provider implementation is not in this branch's ancestry. And the MeetingPoint shape exists here, so its binding stops being optional — a backend that cannot carry one of the four entities cannot serve the app, and nothing optional should let a half-backend register quietly. Also: both usage declarations are named usage_festipod.md, so the stem is now ambiguous as a link. They are referred to by folder path, and both are listed under publish so each provider can re-find its own if it moves. |
||
|
|
e282384e00 |
The Refine seam travels to this base, deliberately unwired
The seam that puts Festipod's persistence behind interchangeable Refine backends was built on `festipod-refine`, over a base this one has since overtaken everywhere else. Carrying the seam rather than the branch keeps the evolved data layer intact and costs nothing: the backend contract, the registry and the provider that mounts Refine depend only on the domain types, so they compile here untouched once `@refinedev/core` is present — the one dependency this adds, installed through pnpm as this project requires. Nothing imports them and the registry is empty, which is the intended state. Wiring the seam means rewriting `FestipodDataContext` against this base's version of it — its own decision, with its own failure modes, and not one to smuggle into a transfer. Landing the files first makes that decision reviewable against real code instead of a diff between two branches. The doctrine travels with the code, because the seam is unreadable without it: the reconstructed observation of `@activitypods/refine-providers` — a package that publishes no engagement at all, hence `type: reconstruct` and a pin on the commit it was read at — our usage declaration beside it, and the brief that arbitrates one data shape for two rights models. So the manifest grows a `publish:` section: this repo still offers no interface, but it does now publish what it consumes, which is the only channel a provider has for learning that. The brief was written where three of the leaves it cites did not exist, and named them in prose to say so. Here they exist, so it links them; and its open deduplication point now reads against this repo's own `materializeAttendance` instead of against a sibling branch. It stays open, and the finding is unchanged: the active set is keyed per deposit, which buys replay idempotence and not person identity, so the count counts deposits rather than people. Two comment zones came over knowingly superseded — runtime hot-switching as what shapes the provider, and a sign-in barrier waiting on something `AuthGate` no longer does. They are recorded as data-layer doc-debt instead of being quietly rewritten, so the rewrite lands with the wiring that settles what they should say. |
||
|
|
319e7082cc |
Re-pin the indexing engagement on the version that can be installed
`1.0.0` declared the data layer as a dependency resolved through a path that existed only in its author's working copy, so no application could install it -- not partially, but at the install itself, which is why none ever ran it. `1.0.1` declares that package a PEER, supplied by the application. That is the shape that makes a single verifier structural rather than something verified afterwards. Nothing exported moved, which is what makes it a patch: the only thing that changed for a caller is a requirement it could never have satisfied. Two facts the new engagement adds, both worth having before wiring anything. The package is published to no registry and distributed as TypeScript source, so whatever builds the application compiles it -- our image installs from git and Bun compiles at serve time, which fits, but a JavaScript-only toolchain could not consume it. And `1.0.0` is superseded rather than withdrawn: the tag stays and keeps resolving, because a pinned reference is never taken away from under a consumer -- a policy the provider holds even for a version that never worked. |
||
|
|
279faa4541 |
Retire a caveat the fix made false, and turn a stale warning into a technique
Four of the five fields the caveat said were silently lost are now persisted, so the caveat is retired rather than trimmed. What was genuinely unique in it -- the inbox predicate being a vestige that must stay unused -- moved into the Event bullet where the shape is described; what merely duplicated the entity leaf went. Only `themes` remains unpersisted, and since nothing reads it back it is a note rather than a hazard. The regeneration warning is reframed rather than deleted. It said the ORM generator had drifted from the committed bindings; that no longer reproduces -- regenerating from the unchanged shape gives byte-identical output. What survives is the technique that established it: run the generator on unchanged input first, so an ORM diff separates cleanly into the author's change and the generator's own. A warning became a way of working. The same stale claim sat independently in the commands leaf and was found by grep, not by the briefing. Recorded where the screen hazards live: the edit form seeds its inputs on first render, so mounted before its event lands in the reactive set it stays blank -- the same class as a value that is empty until a read arrives. Verified rather than assumed: the misleading French date example flagged for correction exists nowhere in the doctrine. It lives in a shape comment and the binding generated from it, both outside this pass, and is noted as such. |
||
|
|
c3d64555d9 |
The data layer is a real external dependency, pinned to a commit
`package.json` named `#main`, where the renamed `packages/polyfill` does not exist, and `pnpm-lock.yaml` still named the package as it was called in July. `pnpm install --frozen-lockfile` -- the Dockerfile's install step -- refused on exactly that mismatch, so the image could not build at all. Both now name the commit the branch was pushed at, and the frozen install passes. The dependency is now genuinely external: installed from git into pnpm's store, with no local overlay anywhere in the resolution. The invariant that justified the overlay in the first place holds -- `@ng-org/web` resolves to the same realpath from the application and from the installed package, so one instance and one verifier. A git-installed package does not carry its own `@ng-org`, where a symlink to the checkout would have. `.project/contracts.yaml` names the same commit as the dependency, so the surface the app is coded against and the package it installs designate one state, and a drift between them becomes visible instead of silent. A tag will replace the commit once the provider settles a convention; the invariant is that the two agree, whatever the ref. Deployment doctrine now carries what a deployer needs and did not have: the pinning discipline, that the frozen install only verifies, the wallet arriving through the environment with its one-directional precedence and its loud failure on a malformed value, that neither the wallet nor its password is a secret, that tailwindcss is a devDependency the server needs at serve time, and that a deployed origin's embedding in the broker's iframe is covered by no test. Nothing has been deployed in this shape yet, and the doctrine says so. |
||
|
|
53c0e095cf |
Code against the polyfill's published contract, and nothing else
The data layer is now reached through one pulled, version-pinned engagement (`.project/concepts/data-layer/contract_polyfill-surface.md`, @1ecf511e9d). That copy is the only reference: the provider's sources are never opened, and what the contract does not answer is a gap raised with it, never worked around here. Surface - `@ng-eventually/sdk` -> `@ng-eventually/polyfill`, one entry point. - `configure` loses `getSession`, `normalizeId`, `currentUser`; the session belongs to the package and its own `init` captures it. - Placement is named by scope alone -- a session is one user, so the app no longer passes an identity it had no way to obtain. This removes a constant that made every user collide on one owner's document. - `init(...)` then `await ensureIdentity()`, in that order, as one sequence: React runs child effects first, so the two calls sat in the wrong order and the contract now makes that throw. - `sessionId` relayed as `string | number`, `materialize` -> `read`. A rejection means "unknown", never "absent" Four places treated a caught error as an empty result. The worst wrote a duplicate participation: an unknown count read as zero defeated the idempotence guard of `joinEvent`. Also fixed: a per-document count, a silently dropped notification shown optimistically anyway, and a failed listing that left the owned-event set empty and disabled the materializer for the whole session. Shared identity is not a Festipod notion A browser context is one user. The per-scenario identity plant is deleted at its source and its five sites; what stays is the deployment's wallet file, which the contract requires an application to serve. Documentation The doctrine no longer describes how the data layer works underneath: five leaves whose subject was internals are gone, a dozen more are re-founded on the contract's own words, and two frozen arbitrations about a deleted screen were removed rather than left to mislead a future session. Test harness It can sign in at last: cucumber runs under node, which does not load `.env`, so the harness never received the wallet material and every scenario silently fell back to an empty local mode. A failed sign-in is now loud on both sides. The suite also releases what it opens and exits on its own -- runs were still resident hours after reporting, holding a browser and two servers. Known red: `@data` cannot be measured. The served wallet accumulates and nothing resets it; moving the browser profile aside does not, since the data lives in the wallet file, not the profile. |