The act affordances on motir.co — follow, subscribe, vote, upvote, comment and in-place overview editing, exactly as the amendment decided
Make the act affordances work on motir.co, exactly as the amendment decided them, against the mechanisms the motir-core act path shipped.
The affordances, and where each one sits on the surfaces already built:
| affordance | surface | producer today |
|---|---|---|
| follow | the project shell (H) | POST/DELETE /api/public/p/{identifier}/follow — 401 without a session |
| subscribe by email | the project shell | POST …/subscribe — already anonymous |
| roadmap vote | the Roadmap tab (I) | POST /api/public-requests/{id}/upvote — session |
| request upvote + comment | the request detail (J) | the same two routes |
| in-place overview editing | the Overview (H) | setPublicOverview, through whatever door F built |
| the account / sign-in treatment in the top bar | the shell | the amendment's row |
This card implements decisions; it does not take them. Where the amendment says a control hands the visitor to app.motir.co and returns them, build that round trip and the return; where it says a control is absent on this host, do not render a disabled stand-in unless the amendment asked for one; where it says a control works anonymously, build it. If a row's mechanism cannot be built as written, stop and amend the record — do not improvise a different mechanism, and above all do not reach for a cookie scope this story exists to preserve.
The one invariant every option shares, and this card's own hard gate: nothing here causes a Domain=.motir.co cookie to be set, read, or required, on either host. That is asserted, not intended.
Anonymous stays first-class. Every surface built so far works logged-out, and it keeps working: an affordance that needs identity degrades to the amendment's mechanism, never to a broken page or an empty panel with no explanation.
Acceptance criteria
- Every row of the amendment's affordance table is implemented on the surface it belongs to, and the card's body maps row → file, with any row the amendment placed elsewhere named and excluded.
- A logged-out visitor sees every read surface exactly as before this card, with each affordance in the state the amendment specifies for an anonymous visitor.
- A visitor who is signed in to
app.motir.cocan complete each act by the mechanism the amendment chose, and lands back on the/p/*page they started from — the return path asserted, not assumed. - Subscribing by email works with no account, end to end.
- No cookie with a
Domainattribute covering.motir.cois set or required by anything this card ships, asserted by a test that inspects the responses of the pages under test. - Each affordance renders its failure state — 401, 403, 429, and an unreachable API — as a state the design draws, not as a thrown error.
- The in-place overview editor is reachable only by a visitor the producing service authorises to manage the project; an unauthorised visitor sees no editing affordance at all.
- No file outside
motir-marketingis touched.
Context refs
motir-core/docs/decisions/public-surface-hosts.md§4 and AMENDMENT 2 — the constraint and the table this card implementsmotir-core/app/api/public/p/[identifier]/follow/route.ts·subscribe/route.tsmotir-core/app/api/public-requests/[id]/upvote/route.ts·comments/route.tsmotir-core/lib/services/publicProjectsService.ts—getOverview'scanManage,setPublicOverviewmotir-marketing/lib/appOrigin.ts·lib/destinations.ts— how a cross-origin hand-off intoapp.motir.cois already built heremotir-marketing/design/public-projects/— the boards for each affordance and its states