Compare commits
2 commits
28bd256ac7
...
1f19bfbdd5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f19bfbdd5 | ||
|
|
dbaf840ebe |
7 changed files with 260 additions and 2 deletions
63
model-outputs/01-architectural-risk-claude-sonnet-4.6.md
Normal file
63
model-outputs/01-architectural-risk-claude-sonnet-4.6.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
model: claude-sonnet-4-6
|
||||
prompt: model-tests/01-architectural-risk.md
|
||||
context: AGENTS.md
|
||||
date: 2026-06-04
|
||||
reference: true
|
||||
|
||||
---
|
||||
|
||||
decision 1: sqlite with "postgres-ready schema"
|
||||
|
||||
the risk is that "postgres-ready" is not a state sqlite enforces — it's a promise
|
||||
the developer keeps. sqlite is dramatically more permissive than postgres: no
|
||||
strict foreign key enforcement by default, no real enum types, no CHECK
|
||||
constraints with the same semantics, different RETURNING behavior, and timestamp
|
||||
handling that silently accepts junk. the gap only surfaces at migration time,
|
||||
which is exactly the worst moment to discover it. the specific trap for this
|
||||
codebase is the reaction model — user + post + emoji + timestamp with no counter
|
||||
normalization is fine, but if you're using sqlite's flexible typing and unquoted
|
||||
column names anywhere, your postgres migration will break on things that look like
|
||||
they should work. the tus resumable upload state also tends to involve upserts
|
||||
and returning clauses that differ between the two.
|
||||
|
||||
mitigation: enforce PRAGMA strict = ON from day one (bun:sqlite supports it). this
|
||||
makes sqlite reject type mismatches the same way postgres would, and it's a
|
||||
one-liner that costs nothing and catches the class of bugs that makes migrations
|
||||
painful.
|
||||
|
||||
---
|
||||
decision 2: federation off via a flag, activitypub data model active from day one
|
||||
|
||||
the risk is not technical complexity — fedify handles that. the risk is that
|
||||
"flag-flippable later" assumes your object URIs are stable and your actor
|
||||
resolution works correctly before you have any external consumers to test against.
|
||||
when you eventually flip the flag, you'll discover that your webfinger endpoint
|
||||
was returning the wrong content-type, your @context was subtly wrong, or your
|
||||
outbox pagination was broken — and you'll find out from confused server admins on
|
||||
the other end, not from a test suite. activitypub interoperability is notoriously
|
||||
hard to verify in isolation.
|
||||
|
||||
mitigation: stand up a second test instance (even just a local second process) and
|
||||
do one real federation handshake before v1 ships, even with the flag off in
|
||||
production. you don't need to turn it on publicly — you just need to know it
|
||||
works. this is maybe two hours of work and it retires the "unknown unknowns" risk
|
||||
entirely.
|
||||
|
||||
---
|
||||
decision 3: magic-link email auth with no passwords and no push notifications
|
||||
|
||||
the hidden complexity here is account recovery under adversarial conditions. magic
|
||||
links depend entirely on email delivery. if the user's inbox is inaccessible
|
||||
(spam filter swallowed the link, mail provider down, user changed email and didn't
|
||||
update), there is no fallback — no password reset, no SMS, no TOTP. for a small
|
||||
invite-only community this is probably fine in practice, but the specific failure
|
||||
mode is: user gets a new phone, opens eutopic, tries to log in, email goes to spam
|
||||
or their old address, and they're locked out with no self-service recovery path.
|
||||
they have to contact you, the admin, directly. that's not catastrophic at 50 users
|
||||
— it's actually fine — but it needs to be a named operational responsibility, not
|
||||
a discovered one.
|
||||
|
||||
mitigation: add a simple admin-side "resend invite / reassign email" capability
|
||||
before the first non-technical user onboards. one endpoint, admin-only, takes a
|
||||
username and a new email. this is 20 lines of backend code and it means account
|
||||
recovery is always solvable without a production incident.
|
||||
42
model-outputs/01-architectural-risk-deepseek-reasoner.md
Normal file
42
model-outputs/01-architectural-risk-deepseek-reasoner.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
model: deepseek-reasoner
|
||||
prompt: model-tests/01-architectural-risk.md
|
||||
date: 2026-06-04
|
||||
|
||||
---
|
||||
|
||||
1. fedify/activitypub from day one, federation off
|
||||
|
||||
the risk is paying a nontrivial complexity tax (uri-based ids everywhere, fedify's
|
||||
type system coupled to elysia, ap protocol shapes in the data model) for a
|
||||
feature that's gated behind an off flag. fedify is a small team and its bun/elysia
|
||||
binding may not keep pace with runtime changes. you'll debug fedify internals
|
||||
before you ever federate a single post. mitigation: wrap all fedify calls behind a
|
||||
thin repository/port interface in the domain layer. if fedify breaks or stalls,
|
||||
you swap to a minimal ap implementation without touching business logic. don't let
|
||||
fedify's types bleed into your controllers.
|
||||
|
||||
2. sqlite with "postgres-ready" schema
|
||||
|
||||
the classic migration trap. sqlite and postgres differ in transaction semantics,
|
||||
query planning, type coercion, and concurrency (wal vs mvcc). writing sql that
|
||||
performs well on both is harder than committing to one. the specific pattern i'd
|
||||
watch: bun:sqlite is synchronous — sqlite calls block the elysia event loop. for
|
||||
5-50 users it's fine, but the moment you need queries that use postgres-specific
|
||||
features (jsonb, partial indexes, ctes for complex follows) you'll have rewritten
|
||||
significant code anyway. mitigation: commit to sqlite fully. use wal mode, measure
|
||||
whether event-loop blocking matters at your scale, and only design a thin query
|
||||
adapter — not a dual-runtime schema. the "just swap the connection string" plan
|
||||
doesn't survive contact with real query differences.
|
||||
|
||||
3. tus.io resumable uploads from the first alpha
|
||||
|
||||
the biggest hidden complexity in the stack. tus is a protocol, not a plug-in. on
|
||||
the flutter side you need: platform-specific background upload services
|
||||
(urlsession on ios / workmanager on android), a chunk-state machine, and resume
|
||||
logic. on the server: chunk reassembly, temp storage for partial uploads, cleanup
|
||||
of abandoned transfers. for 5-50 users posting a few photos a day, a simple
|
||||
multipart upload with exponential backoff covers 95% of the same use case with a
|
||||
fraction of the surface area. mitigation: ship the alpha with plain multipart
|
||||
upload behind a clean interface. add tus only when real-world users on bad
|
||||
connections demonstrably need it. you'll know when because they'll tell you — 5
|
||||
people on a train is a clearer signal than any architecture doc.
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
model: gemma-4-e4b-it-OptiQ-4bit
|
||||
prompt: model-tests/01-architectural-risk.md
|
||||
context: AGENTS.md + docs/CONCEPT.md + docs/OPEN-QUESTIONS.md
|
||||
date: 2026-06-04
|
||||
|
||||
---
|
||||
|
||||
thinking carefully... i'm looking at concept.md, open-questions.md, and the
|
||||
implied context from AGENTS.md—even though i haven't read AGENTS.md yet, the other
|
||||
docs give enough signal to start the high-level risk assessment for a pre-build
|
||||
review, focusing on architecture rather than feature completeness yet. the core
|
||||
tension seems to be "simple feel vs. robust future proofing."
|
||||
|
||||
i see three high-risk areas stemming from the confluence of tech choices and
|
||||
philosophical constraints.
|
||||
|
||||
the first is integrating activitypub/fedify while keeping federation disabled
|
||||
(lines 81-83 in concept.md). the risk here isn't just that it's "upfront cost is
|
||||
minimal," but rather the operational overhead of managing a protocol layer that
|
||||
could suddenly be flipped on, which introduces non-trivial state management and
|
||||
dependency complexity even if the feature is inert. making those URIs standard
|
||||
from day one sounds good, but keeping them "off" while carrying the plumbing for
|
||||
"on" creates latent complexity debt.
|
||||
|
||||
mitigation: define an extremely explicit, versioned configuration flag (e.g.,
|
||||
activitypub_federation_enabled: false) checked at runtime by a monolithic routing
|
||||
service, not loosely scattered. if this flag is ever toggled in production (even
|
||||
for staging), the code path executing federation logic must be instantly testable
|
||||
and roll-back friendly via config change alone.
|
||||
|
||||
the second big risk is the background/resumable upload pipeline (tus.io, lines
|
||||
91-95). meta's perceived "instantness" versus a distributed upload mechanism is a
|
||||
major user experience divergence. while the architecture supports it,
|
||||
implementation complexity skyrockets when considering edge cases: network drops
|
||||
mid-upload across multiple background processing contexts (ios background tasks,
|
||||
android workmanager) combined with filesystem/s3 migration (line 52). state
|
||||
synchronization for resumable uploads across these heterogeneous environments is
|
||||
hard.
|
||||
|
||||
mitigation: start by locking down the mobile client's upload state caching locally
|
||||
(e.g., using a simple encrypted sqlite file on the client device) before tackling
|
||||
server-side resilience for version 1. initial V1 should prioritize making the
|
||||
upload appear instant to the user via local caching, and only push the full
|
||||
resiliency layer post-MVP inside a tight scope.
|
||||
|
||||
the third risk is unifying the "no hierarchy" value with the feature set,
|
||||
specifically around reactions and potential future comments. in concept.md (lines
|
||||
122-139) and open-questions.md, there's a constant pivot away from counts/public
|
||||
visibility (reactions are stored as user + post + emoji + timestamp, not counters,
|
||||
confirmed in closed section 32). while this protects the value statement against
|
||||
"dopamine grift," it heavily complicates feed sorting/discoverability if those
|
||||
values ever become necessary. the user base is small, but scaling this philosophy
|
||||
becomes difficult.
|
||||
|
||||
mitigation: codify the "no counts" rule as an immutable architectural constraint
|
||||
that is flagged in the AGENTS.md (line 74) and enforced by linting checks against
|
||||
any future PR that introduces a counter field for engagement. if the community
|
||||
later demands "what are people thinking?" (i.e., counts), the system must require
|
||||
a full re-architecture via a staged 'v2 migration' rather than incremental feature
|
||||
creep.
|
||||
|
||||
i identified three risks:
|
||||
1. activitypub plumbing complexity with federation off.
|
||||
2. complex state synchronization for resumable uploads across mobile platforms.
|
||||
3. maintaining "no hierarchy" by forbidding engagement counters entirely.
|
||||
33
model-outputs/01-architectural-risk-glm-4.7.md
Normal file
33
model-outputs/01-architectural-risk-glm-4.7.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
model: glm-4.7
|
||||
prompt: model-tests/01-architectural-risk.md
|
||||
date: 2026-06-04
|
||||
|
||||
---
|
||||
|
||||
three highest-risk decisions:
|
||||
|
||||
storage migration (filesystem → s3-compatible). open priority 0 question flagged
|
||||
in OPEN-QUESTIONS.md. moving existing user media after launch means rewriting
|
||||
database references, handling broken links, and likely requiring a period where
|
||||
both systems coexist. risk: data loss or broken media references during migration.
|
||||
mitigation: write to both filesystem and s3-compatible storage from day one
|
||||
(dual-write), making migration a matter of retiring the filesystem backend rather
|
||||
than moving data.
|
||||
|
||||
sqlite → postgres migration path. called "postgres-ready" but no documented
|
||||
strategy exists. sqlite and postgres have different constraint semantics,
|
||||
transaction behaviors, and query capabilities. a photo-first app will hit sqlite
|
||||
limits faster than a text-only one. risk: architectural assumptions that don't
|
||||
port, breaking migrations or queries at scale. mitigation: use a repository
|
||||
pattern to abstract database specifics, add a migration test suite with realistic
|
||||
media volume early, and document which postgres features you're avoiding to stay
|
||||
sqlite-compatible.
|
||||
|
||||
fedify integration without v1 activation. fedify is in the stack but federation is
|
||||
off, planned for v2/v3. building the core data model without understanding
|
||||
fedify's requirements could force major refactoring later. risk: discovering
|
||||
incompatibilities between your current schema and fedify's activitypub model
|
||||
constraints after users have data. mitigation: prototype a minimal fedify
|
||||
integration now to understand its schema and protocol requirements, then design
|
||||
your core data model with those constraints in mind even if federation remains
|
||||
inactive.
|
||||
48
model-outputs/01-architectural-risk-qwen3.5-9b.md
Normal file
48
model-outputs/01-architectural-risk-qwen3.5-9b.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
model: qwen3.5-9b
|
||||
prompt: model-tests/01-architectural-risk.md
|
||||
context: AGENTS.md
|
||||
date: 2026-06-04
|
||||
|
||||
---
|
||||
|
||||
the three highest-risk architectural choices are the is_admin flag without RBAC
|
||||
primitives, deferring DMs to v2 via external handles instead of in-app messaging,
|
||||
and relying on fs storage with no migration plan until after media ingestion is
|
||||
live.
|
||||
|
||||
first, locking down "admin-only surveys" with a single boolean flag on the user
|
||||
table creates a single point of failure for trust and access control. if you need
|
||||
to revoke admin rights or split duties later without rewriting the core auth flow,
|
||||
you are stuck. the risk here is operational lock-in where one person controls all
|
||||
feedback loops and the app has no mechanism to audit who actually created what. i
|
||||
estimate a 40–60% chance you will face a hard refactor when v2 needs granular
|
||||
permissions for events or fundraising moderation. mitigate this by designing user
|
||||
records with an empty policy map {} that maps roles (admin, mod, poster) to action
|
||||
sets upfront in the schema, even if only one role exists now.
|
||||
|
||||
second, handling DMs via external social handle strings means you lose the ability
|
||||
to resolve addresses within eutopic and force users to leave your app for
|
||||
conversation. this is a user retention risk because photo comments will naturally
|
||||
drift toward private chat, but you've built no bridge into that space. it also
|
||||
complicates v2 scope creep if you later decide to build DMs: you'd need to
|
||||
retrofit an internal message store or convince users to migrate their existing
|
||||
external threads. the probability of needing to rewrite the onboarding and profile
|
||||
flow is 30–50%. mitigate this by implementing a minimal internal /messages table
|
||||
with ephemeral in-app routing (pushed to v2) now, keeping it isolated from the
|
||||
main feed logic so you can toggle visibility without touching backend routes.
|
||||
|
||||
third, storing media on local fs before committing to an s3-compatible abstraction
|
||||
layer creates silent failure modes when disk space fills up or hardware degrades.
|
||||
with 5–50 users each uploading 10 photos at 5mb average, you'll hit a terabyte
|
||||
wall in ~100 days if growth accelerates. migrating mid-data is painful because of
|
||||
checksums and broken links. the risk surfaces only after you've ingested critical
|
||||
community content. i see a 60–70% chance this path forces an emergency rewrite
|
||||
during v2 prep when disk space becomes tight or backups fail. mitigate by mocking
|
||||
MediaStorage as an interface with fs impl now, but enforce a pre-check on first
|
||||
upload that writes metadata to a central catalog table and verifies free-space
|
||||
before accepting the file stream.
|
||||
|
||||
you're building something intentional here, but these three decisions will bite if
|
||||
you ship without planning for their evolution paths.
|
||||
|
||||
✻ Crunched for 1m 2s
|
||||
|
|
@ -4,6 +4,6 @@ version: 1
|
|||
|
||||
---
|
||||
|
||||
read @AGENTS.md. you are a senior backend engineer reviewing this project's architectural decisions before the first line of code is written.
|
||||
read @AGENTS.md and @CONCEPT.md and @OPEN_QUESTIONS.md. you are a senior backend engineer reviewing this project's architectural decisions before the first line of code is written.
|
||||
|
||||
identify up to three decisions that carry the most technical risk or hidden complexity. for each one: name the decision, explain the specific risk, and suggest one mitigation. be direct — this is a pre-build review, not a validation exercise.
|
||||
7
model-tests/05-short_subprompt.md
Normal file
7
model-tests/05-short_subprompt.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
tests: stack analysis, constraint awareness, length discipline
|
||||
context: AGENTS.md
|
||||
version: 1
|
||||
|
||||
---
|
||||
|
||||
read @AGENTS.md and provide thoughts on the `## stack (settled)` section. your response should be a general analysis of the strengths/weaknesses of the stack. limit your response to max 6 sentences.
|
||||
Loading…
Reference in a new issue