StandMeet 노트
StandMeet 뒤에 있는 공개 설계 노트: 동기, 아키텍처, 핵심 설계와 그 트레이드오프를 작성자의 StandMeet 코퍼스 위키에서 그대로 가져옵니다.
이 노트들은 영어와 중국어로 쓰였습니다. 아래에는 영어판을 연결해 두었습니다.
모든 노트
- architectureEach pillar is a node under key-designs, carrying its components, code paths, status, and design pages:
- Confusables — terms that look alike and aren'tThe vocabulary collisions in this system, each split precisely. When a doc says one of these words unqualified, check here.
- Deployment — self-hosted, single-tenantStandMeet deploys as a self-hosted, single-tenant, single-box app. This is the shape the product demands, not a limitation to fix later — and the code's lack o…
- key designsThe non-obvious, load-bearing design decisions, organized as seven pillar nodes (each a folder with its design pages as children). The through-line: StandMeet …
- Pillar 6 · Access control (the valves)Who may see and do what — the most heavily tested pillar (the acl-* e2e matrices). Entry is by access code (= invitation, QR); a code issues against a role who…
- access control diagram coverageThe pillar's class diagrams live on the design pages they belong to; this page is the coverage gate.
- ACL & quota granularityNotation:
- byoai browser vaultThe visitor's own key is XSS-resistant on the browser side: a non-extractable AES-GCM CryptoKey lives in IndexedDB (JS can call encrypt/decrypt but never read …
- BYOAI key envelopeA visitor's own model key (BYOAI) never touches server storage or Redis. The browser keeps it and wraps it per request in an X-Byoai-Key header: AES-256-GCM, w…
- Coded landing /c/<slug> and rotating the code stringMotivating problem. The résumé PDF (resume-composer-one-renderer) prints <public_url>/?code=<code> in its QR. That is a credential in a URL: it lands in browse…
- Owner keypair auth (Ed25519 Sigv1)The owner MCP handle (/mcp/*) gates every HTTP request with a valid Sigv1 signature — legacy Bearer PAT was removed when keypair auth replaced PATs (routes/mcp…
- Owner sessions and abuse controls: the small valves nobody documentsThe big valves have pages — the three-layer ACL (access-control list, acl-and-quota-granularity), Sigv1 (owner-keypair-auth), the embed JWT (JSON Web Token, em…
- RoleSnapshot frozen at session issueWhen a session is issued, the entire role state (corpus URIs, prompt body, skill prompts, allowed tools, denied capabilities, denied corpus globs, waypoints, p…
- Trusted identity via tool-call _metaThe session's trusted identity — OwnerID, Subject{Kind, ID} (an access code or an outbound key; it was CodeID until 2026-08-20, 162f09833, when key-path sessio…
- Pillar 5 · Agent core (the loop)The interpretation engine — where the product thesis (same corpus, per-audience presentation) executes. inference (backend/internal/conversation/inference/) wr…
- Agent as an injectable driverAgent core = independently launchable module via Bridge/Driver.
- agent core diagram coverageThe module's class diagrams live on the design pages they belong to; this page is the coverage gate — what's diagrammed, what isn't yet.
- detached turn persist at completionThe agent turn runs on context.WithoutCancel — a client disconnect (refresh / close) doesn't cancel it; the stream completes and lands in the DB (only a WithTi…
- Entry-agnostic agent (inward/outward symmetry)The agent is entry-agnostic: entries are just consumers that fill a neutral session context and invoke it.
- Eval-harness on the prod loopThe eval-harness imports only the public agentcore facade (never internal/) and runs the byte-for-byte same agent loop as prod — so a bug found in eval is a re…
- Force a final answer on terminal errorIf the agent loop ends in an error having produced zero assistant text (max iterations hit, hallucinated tool name, etc.), instead of surfacing an error it mak…
- Ghost steering — one suggested message that bends the conversationThe owner wants visitor conversations to converge toward per-role destinations (see project X, grasp the differentiation, book a call) — but the agenda is the …
- System-prompt hash for regression detectionThe composed system prompt is SHA-256 hashed; an invariants check builds it 3× and asserts the hash is identical (backend/internal/capabilities/capreg/system_p…
- unbuffered sse passthroughThe /api/v1/agent/turn Next route does not go through next.config rewrites — those buffer the upstream SSE, so the browser would receive every frame at once at…
- Pillar 2 · Capabilities (they speak MCP)The agent's hands, organized as plugins on the MCP standard (copied verbatim — no private protocol). capreg is the registry: deterministic assembly order (the …
- Capabilities — diagram coverage (assembly side vs consumption side)Same two-sided cut as connector-diagram-coverage: the assembly side (how capabilities register and get exposed per session) and the consumption side (what the …
- A capability declares its own quota, config, and storemcp-capability-plugins explains that a builtin is a manifest plus an MCP process in a sandbox. This page is about the part the host used to hand-write for each…
- capsocket — one narrow socket per capabilitySandboxed builtin plugins (summarize / retrieval / booker / mail-sender; ask-visitor is sandboxed too but declares no host ops, so it gets no socket at all) ru…
- The feature floorThe contract governing the externalization migration — moving a capability out of the core must not drop any of these cross-cutting behaviors. The floor items …
- mcp capability pluginsThis page is the capability plane — StandMeet as MCP host (see confusables). The agent's external tools / skills (retrieval, booker, summarize, ask_visitor + o…
- Skills: three-level progressive disclosureA skill is not one-tool-per-script (that explodes the tool list and bloats the system prompt) — and a skill is not a capability either: it's an authored artifa…
- ui:// MCP-Apps cardsPer-tool interactive cards in the chat, delivered as MCP-Apps ui:// resources, rendered in a sandboxed iframe talking to the host via postMessage. All per-tool…
- Pillar 3 · Connector (the credentialed edge)Every credentialed contact with the outside world goes through one layer: connector.Hub + category slots. Consumers (agent capabilities, platform features, the…
- Connector dependencies — Requires, resolved fail-closedThe formal interface between the capabilities pillar and the connector pillar — fail-closed and consumer-agnostic by design. A plugin manifest declares Require…
- Connector — diagram coverage (registry side vs caller side)The connector module is two designs sharing one package: the registry side (how a connector gets installed, credentialed, activated) and the caller side (how a…
- Connector egress guard (SSRF defense)Once an owner can upload an arbitrary OpenAPI connector, the target URL is attacker-influenceable — a classic SSRF surface (point it at 169.254.169.254 or an i…
- Connector plugins — installable, consumer-agnosticA connector is NOT MCP — it speaks category contracts, not the MCP wire protocol; the two plugin axes touch only at connector-deps (confusables, incl. action v…
- Idempotent booking, write-only retryCalendar events.insert is non-idempotent: if the connection drops after Google created the event but before the response, a blind retry double-books. So the id…
- Pillar 1 · Corpus (the asset)The owner's knowledge base — the moat. One table, corpus_notes, with a genre column (raw / wiki / output / subjectivity / writing) — the three tiers are still …
- backlinks as rebuilt edge tables[[X]] lives literally in the body (never rewritten at storage). On every save, the code extracts all [[X]], resolves them to ids, and deletes all out-edges the…
- corpus diagram coverageThe pillar's class diagrams live on the design pages they belong to; this page is the coverage gate.
- Corpus retrieval — walk the graph, not just the treeToday (landed): corpus_search / corpus_read / corpus_list / corpus_links / corpus_grep / corpus_map / corpus_peek / corpus_resolve — eight tools over a Meilise…
- Derived path — "the corpus is a filesystem"corpus_notes (every genre — wiki / output / subjectivity, and raw too since d925d9081, 2026-07-09) has a parent_id self-ref tree but no path column. The addres…
- Global asset pool: one store, reference accountingMotivating problem. Before 2026-09-05 an asset belonged to its holder — storage_key = <holder_id>/<asset_id>, "delete holder → delete its assets in the same tr…
- obsidian sync mechanismBidirectional sync between StandMeet and an Obsidian vault. Shaped like Quartz / obsidian-importer: two buttons, each a batch job, owner-triggered manually — n…
- Protocol — frontmatter field-source contractFor every field, two questions: where does its value really come from, and who reads it — Obsidian, StandMeet, both, or neither. Anything whose source is more …
- Rendering & extensibility of synced notesHow StandMeet supports the presentation / extensibility layer of the notes it syncs (theorem callouts, math, diagrams, dynamic widgets) — the settled design.
- Vault ingestion: single vault + ignore rulesStandMeet's account syncs a single Obsidian vault as its live source — Option A. The two alternatives are deferred:
- rendering enginesStandMeet's markdown pipeline renders rich content across chat answers, wiki/output pages, and writings (app/src/components/page/markdown.tsx): remark-gfm + re…
- KaTeX (math)Math rendering. StandMeet: remark-math → rehype-katex (katex ^0.16). Obsidian: MathJax.
- Mermaid (diagrams)Text-based diagrams. Obsidian: built-in. StandMeet: a code component override detects mermaid (isMermaidCode / mermaidSource, app/src/components/page/markdown-…
- TikZ (precise math figures) — shippedFills the gap mermaid can't: precise mathematical figures — geometry constructions, commutative diagrams, coordinate/labeled boxes, function curves. A ```tikz …
- Three-tier corpus by promotionraw → wiki → output: draft → curated → polished. Entries are promoted, not copied — since the tiers folded into one corpus_notes table (d925d9081, 2026-07-09) …
- Writings ⇄ vault: the obsidian import/export subsystemToday (landed): manual, owner-triggered, batch architecture. GET /api/admin/obsidian/export streams a standmeet-vault.zip (no temp file); POST /api/admin/obsid…
- StandMeet × the eight controlsRead as a cybernetic machine, StandMeet is a control apparatus that destroys a stochastic LLM's variety and converges it onto one goal G = "answer as the owner…
- The embed credential never carries the codeMotivating problem. A <standmeet-chat> widget runs on a site StandMeet does not control, and its session must land on an access code — the code is what carries…
- Microsites: owner-written pages the instance builds and hostsThe instance root is the reserved slug home (HomepageSlug, owner/usecase/microsite.go:34; a5e1cada9 on 2026-09-04, template 77aee7dc6). The app middleware prob…
- Pillar 4 · Monitor (the thinnest pillar)Call-time telemetry of the running system: the host's second cross-cutting controller, distinct in timing from ACL — ACL acts at session establishment (via "no…
- Product-owned upgrade: the instance rebuilds itself in placeMotivating problem. In the image-based stack the backend deliberately has no docker.sock (deployment) — it cannot pull images or recreate its own containers. U…
- Résumé composer: one renderer draws the canvas and the PDFMotivating problem. The résumé is the outbound half of chain-hiring: the PDF carries a QR (quick-response) code whose URL admits the recruiter under an access …
- The service handle (StandMeet as MCP server)Not a pillar — the outward face. This node is deliberately separate from capabilities because the two are the easiest concepts in the system to conflate (confu…
- The as-MCP facadeThis page is the service handle — StandMeet as an MCP server (the outward plane), not the capability plane where our own agent consumes plugins as host — see c…
- UI–MCP parity — whatever the UI can do, the handle can doEvery owner operation reachable through the admin UI is also reachable through the service handle (StandMeet-as-MCP-server) — so the owner's AI session is neve…
- Pillar 7 · Structure & discipline (the foundation)The ground the other six pillars stand on. Code shape: Go packaged by domain (internal/<domain>/{entity,usecase,repo,db,ops,facade} — the by-layer domain → use…
- A gate that cannot go red is not a gateTen of the fifty-five check-* entries under infra/scripts/ (counted 2026-09-07) exist only to attack the other forty-five. Their shared opening line is the doc…
- Backend domain modules — package by domainThe backend was packaged by layer, not by domain (until 2026-07-27). That was the root debt behind a whole class of tangles (a connector importing capabilities…
- Builder: a separate service that claims workMicrosite builds (the surface was called "custom pages" until the rename, e7fe80e91, 2026-09-05) run in a separate builder service, not the main app — so the A…
- Two convergence points — outbound and inboundThe deepest structural idea in the backend, and the one that had no note. Everything a capability can do, and everything it can ask back for, passes through ex…
- Display errors — one envelope, log/client separationErrors that reach the user are wrapped in a single envelope shape; the cause is audited separately in logs, never exposed to the client.
- Each domain: internal DDD layout + a thin outward facadeThe domains under internal/<domain>/ have no outward-facing exposure layer. To use a domain you must read the whole thing to find its methods — there is no sin…
- Ephemeral / append-only over statefulA recurring taste across the codebase: don't keep mutable state you can derive or append.
- external means fully externalAn externalized capability owns its own storage too. If the kernel still holds the table, the capability was relocated, not externalized — and a tidier address…
- Facade directions — two trust planesfacade-parity made every facade a projection of one registry. That model had no direction axis — its only base reaches were OwnerRead() / OwnerAction(), and it…
- facade parityOne registry; every facade is generated from it or verified against it. Never a second hand-written description of the same capability.
- Judgment audit — the discipline beyond lintThe split: lint / type / test guard mechanical correctness (mechanical-guardrails); the audit guide guards judgment quality — "mechanical correctness ≠ clean a…
- mechanical guardrails"Mechanical constraint over social argument" made literal. It has grown from a handful of linters into 55 check-* entries under infra/scripts/ — 45 guards plus…
- one source per ui primitiveTwelve gates, one doctrine: every visual primitive has exactly one definition, and a build-time guard makes the second one impossible. This is where the produc…
- Ordering: the depended-upon goes firstA rollout rule, and a rule about who decides the rollout.
- Owner MCP facade = generic discovery + invoke over the two containersThe owner's agent (owner's own MCP client / Claude Code) must reach capabilities the same generic way the visitor agent does: discover from the container, invo…
- Owner-script sandbox hardeningOwner-authored skill scripts (skill_run_script, see skills-progressive-disclosure) are untrusted, so they run hard-sandboxed: --network=none (can't exfiltrate)…
- structure diagram coverageThe pillar's class diagrams live on the design pages they belong to; this page is the coverage gate.
- Subjectivity record notes: an ACL granularity problem(was "Subjectivity owner-visibility (gate-one tightening)" — renamed: "owner" was the wrong frame. Nothing varies about owner visibility; the whole corpus is t…
- productWhat it's for, what it is, and the lines around it.
- Boundaries — what it is NOTStandMeet is not a job-seeking tool. Hiring is an obvious application (a recruiter pre-reads, then asks better follow-ups), but the owner's own use comes first…
- Design principles (philosophy consistency)Every design choice traces back to an articulated stance — that internal consistency is a hard requirement, not decoration.
- differentiationvs input tools (Notion / Glasp / Readwise). They solve input — highlighter, note-taker, journal. They don't solve retrieval-by-others-in-your-voice. A Notion p…
- Product introductionStandMeet inverts the compression. You curate a knowledge base of who you are and what you've actually done; then you — or a visitor — query it, and an AI answ…
- motivationWhy StandMeet has to exist — the problem, the seed insight, the timing, and the fit.
- AI conversation is the thinking substrateThe seed insight, from lived experience: conversation with an LLM is now where substantive thinking actually happens. Explaining a complex view to Claude, you …
- Don't make me repeat myselfThe sharpest, most concrete pain — and the strongest evidence the product is real. An articulated thinker pays a steep cost being asked the same thing over and…
- founder product fitSijie is the product's target user — not a marketing claim, an architectural advantage. Years of AI-conversation substance lost; LinkedIn under-represents him;…
- The interpretation economyFor 25 years the internet ran on an attention economy — shout, get eyeballs, perform on LinkedIn. It's shifting to an interpretation economy: the whole web is …
- lossy self presentationThis bites hardest for a networked thinker — someone whose ideas live in a dense graph while every capture-and-delivery channel is stubbornly linear. Three los…
- stiff questions soft captureInterview-shaped questions — "tell me about a time you…" — are stiff: they retrieve episodes, and episodes cannot be crammed. Asked cold, even a person rich in…
- A transaction needs differenceHiring — and most high-stakes first contact — is at bottom a transaction, and a transaction needs difference: a reason to pick you over the alternative. The ré…
- why nowThree enablers converge:
- thesisThe loop: the user agentically curates the good parts of an AI conversation → pushes them to StandMeet via MCP → the corpus accumulates → the corpus serves mul…
- Requirements → design (the bridge)The missing middle between product and architecture — how the product surface decomposes into the seven pillars, traced BOTH ways: every promise to its enginee…
- Chain · Explicit push — AI conversations become a curated corpusNothing enters except what the owner deliberately curated and pushed; the private substrate becomes a durable public-facing layer only through deliberate acts.
- Chain · Hiring — the first application, not the productboundaries — hiring is an application on the foundation, explicitly NOT the product. transaction-needs-difference — a transaction needs difference; the résumé …
- Chain · Interpretation — a visitor asks, the corpus answers in your voiceAnyone can ask a specific question and receive a specific answer phrased in the owner's voice, grounded and cited, framed for their role — one corpus, lineariz…
- Chain · Machine-readable — when the asker is an agentinterpretation-economy — the web shifts from attention to interpretation economy: "they don't ask you — they ask an AI"; an agent won't fill gaps charitably, i…
- Chain · Owner-first — the external brain before the audienceintroduction — "the first user is you — an external brain over your own thinking; others querying is a second surface". boundaries — "not a job-seeking tool; t…
- Chain · Selective access — who may see what, frozen at issueStatus: DEEPEST CHAIN — design finalized, heaviest tests.
- Chain · Sovereignty — your infra, your keys, your trust boundaryintroduction — the corpus is yours to curate and push, never scraped; the act of attaching it is the trust boundary. design-principles — architectural predicti…