164 lines
7.1 KiB
Markdown
164 lines
7.1 KiB
Markdown
# ADR-0005: Split Phase 3 into three subphases
|
|
|
|
**Status:** Accepted
|
|
|
|
> **2026-05-07 forward note:** the "3-minute replace-window
|
|
> enforcement" line items below describe the value as
|
|
> originally implemented. Updated to **15 minutes** in Part
|
|
> 70; see ADR-0001 Amendment 2026-05-07 for the rationale.
|
|
|
|
> **2026-05-12 forward note (Part 120 audit):** the
|
|
> "Go service" / "Go relay" / "Go indexer" framing below
|
|
> describes the original Phase 3a/3b implementation plan.
|
|
> Both shipped as **Node.js/TypeScript** services (`tsx` as
|
|
> the runtime). The rationale for choosing TypeScript over
|
|
> Go is captured in ADR-0008 §"Writing the indexer in Go
|
|
> instead of Node.js/TypeScript" (no actively-maintained Go
|
|
> library for Blurt signature verification means we'd
|
|
> re-implement; `@beblurt/dblurt` gives us the full verify
|
|
> path in TS). This ADR is preserved with the original Go
|
|
> framing intact for historical accuracy.
|
|
**Date:** 2026-04-18
|
|
**Deciders:** project maintainer
|
|
**Supersedes:** Plan v1.3 §348 description of Phase 3 as a single phase
|
|
|
|
## Context
|
|
|
|
Plan v1.3 described Phase 3 as a single deliverable covering: posting
|
|
relay, account creation UI, indexer, peer gossip, REST + RSS,
|
|
order browse + filter UI, 3-minute replace-window enforcement, sybil
|
|
fee logic, and self-trade detection.
|
|
|
|
After completing Phases 1 and 2, several properties of that original
|
|
scope became clear:
|
|
|
|
1. **Scope is large.** Each bullet above is at least one development
|
|
session of focused work, several are two or three. A single-tarball
|
|
phase would mean 10+ turns between testable deliverables.
|
|
|
|
2. **Infrastructure precedes feature work.** The relay and indexer
|
|
are Go services, new to the repo; they need scaffolding (module
|
|
layout, Postgres schema, build system, deployment scripts)
|
|
before feature code can land. Without a mid-phase checkpoint,
|
|
the user has to accept a long stretch of "trust me, this is all
|
|
necessary" work before anything is visible.
|
|
|
|
3. **Each bullet has distinct value on its own.** Account creation
|
|
works without the orderbook UI. Orderbook browse works before
|
|
posting is wired. Each slice is individually shippable to a
|
|
staging environment, which means the user can poke at real
|
|
services and report issues mid-phase rather than at the end.
|
|
|
|
4. **The operator has now completed the Blurt account registration
|
|
prerequisites.** `morphit` and `morphit-relay` exist on-chain as
|
|
of 2026-04-18. This unblocks the relay subphase specifically —
|
|
we can start it immediately rather than gate it behind user
|
|
action.
|
|
|
|
## Decision
|
|
|
|
Phase 3 is split into three subphases, each producing a standalone
|
|
tarball:
|
|
|
|
- **Phase 3a — Relay + account creation.** Go relay service that
|
|
accepts signed `account_create_with_delegation` ops from users and
|
|
pays the Blurt RC cost. Client-side account-registration UI that
|
|
collects a chosen Blurt account name, signs locally with the user's
|
|
owner key via `useOwnerKey()`, hands the op to the relay, and
|
|
activates the user's display-name broadcast flow. Exit criterion:
|
|
a first-time user can onboard end-to-end and end up with a real
|
|
Blurt account without Morphit ever holding their keys.
|
|
|
|
- **Phase 3b — Indexer + orderbook read.** Go indexer service that
|
|
streams the Blurt chain and materializes Morphit ops into a
|
|
queryable Postgres database. REST + RSS endpoints with the full
|
|
filter set promised in the `rss_feeds` FAQ entry. SvelteKit
|
|
orderbook route wired to live data. Peer-to-peer gossip between
|
|
indexer instances (so the user's app has more than one data
|
|
source). Exit criterion: a visitor can browse live orders on
|
|
morphit.io, filter them, and subscribe to an RSS feed of
|
|
matching orders — even before any orders exist to browse.
|
|
|
|
- **Phase 3c — Order posting + enforcement.** Client-side compose UI
|
|
for new orders. `morphit_order_v1` + `morphit_order_replace_v1`
|
|
ops with on-chain signing via `useActiveKey()` for BLURT fee
|
|
payments. 3-minute replace-window enforcement at the indexer
|
|
(per ADR-0001). Sybil fee logic (escalating-per-24h). Self-trade
|
|
detection. Optional featured-slot auction. Exit criterion: a user
|
|
can post an order and another user can see it; the fee path works
|
|
for all three fee currencies (BTC / XMR / BLURT).
|
|
|
|
## Alternatives considered
|
|
|
|
### Single monolithic Phase 3
|
|
|
|
- **Pros:** less ADR bookkeeping; one tarball to track.
|
|
- **Cons:** no intermediate testability; 10+ turns of work with no
|
|
user-facing deliverable until the end; any scope creep pushes the
|
|
whole phase out; harder to roll back a problematic piece without
|
|
unpicking unrelated work.
|
|
- **Rejected.**
|
|
|
|
### Split into two subphases (relay+account vs indexer+orderbook+post)
|
|
|
|
- **Pros:** only one mid-phase checkpoint to manage.
|
|
- **Cons:** the indexer-plus-post bundle is still 6+ turns and
|
|
inherits the same "no intermediate testability" problem between
|
|
them. Also conflates "read path works" with "write path works,"
|
|
which are genuinely separate engineering concerns worth isolating.
|
|
- **Rejected.**
|
|
|
|
### Four+ subphases
|
|
|
|
- **Pros:** even finer granularity.
|
|
- **Cons:** diminishing returns. Relay and account-creation really
|
|
do belong together (the relay exists to serve the account-creation
|
|
flow and little else for now). Similarly, order posting and its
|
|
enforcement/anti-abuse logic belong together — shipping posting
|
|
without enforcement would be a live abuse vector on mainnet Blurt.
|
|
- **Rejected.**
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
|
|
- Each subphase ends with a testable deliverable on staging.
|
|
- Scope creep in one subphase doesn't block the others from shipping.
|
|
- The user gets three opportunities to redirect the design mid-phase
|
|
rather than one opportunity at the end.
|
|
- Go infrastructure scaffolding (module layout, Postgres wiring,
|
|
build system) lands in 3a and is amortized across 3b and 3c.
|
|
|
|
### Negative
|
|
|
|
- Three tarball handoffs instead of one. Each has its own
|
|
extract-and-review overhead for the user.
|
|
- Two `REVIEW-PHASE3a.md` / `REVIEW-PHASE3b.md` / `REVIEW-PHASE3c.md`
|
|
documents instead of one. Disciplined but not hard.
|
|
- Subphase boundaries may need to move as reality pushes back.
|
|
E.g., if the relay ends up smaller than expected, we might pull
|
|
some indexer scaffolding into 3a. The three-phase structure is
|
|
the plan, not a contract — an ADR-0006 can re-draw the lines if
|
|
needed.
|
|
|
|
### Follow-up work
|
|
|
|
- `REVIEW-PHASE2.md` entries P2-1 (Blurt account registration)
|
|
and the operator-action-items section in PLAN.md are now
|
|
marked complete; 3a can reference those as done rather than
|
|
blocking on them.
|
|
- Carry-forward item #11 from Phase 1 (self-hosting docs) lands
|
|
in 3b, when the indexer is the first Go service users might
|
|
want to self-host.
|
|
- Carry-forward items #16 (WhaleVault / Gravity) and the posting
|
|
relay's owner-key-never-in-browser invariant interact in
|
|
Phase 3a; the relay protocol must accept an externally-signed
|
|
transaction blob so extension-based signing works out of the box.
|
|
|
|
## References
|
|
|
|
- Plan v1.3 §348 — original Phase 3 single-phase definition.
|
|
- ADR-0001 — `custom_json` replacement ops (3c enforcement).
|
|
- ADR-0002 — live keys policy (3a `useOwnerKey()` pattern).
|
|
- REVIEW-PHASE2.md — Phase-1/2 carry-forward items that land in
|
|
each subphase.
|