# Design: Bundle Hygiene (formerly "Dictionary Marketplace") **Author:** zimin.an **Date:** 2026-05-12 **Status:** PROPOSED v2 (post `/office-hours` + cross-model challenge) **Supersedes:** v1 «Dictionary Marketplace» (Approach B: full registry + browse UI + dry-run preview + install dialog, 10-14d) **Scope:** ДЗЗ domain, single-tenant (Approach C-revised — bundle format spec + publisher CLI, NO consumer UI) **Sprint estimate:** **2-3 days CC**, hard cap. Anything beyond requires new design doc. **Blockers:** none --- ## TL;DR v1 предлагал full marketplace (Nexus registry + browse UI + install dialog + dry-run preview + multi-tenancy + dep resolution) за 10-14 days. После `/office-hours` premise challenge + cross-model challenge — **v1 был over-scoped для N=1 customer** (ЦУОД anchor only сегодня). **Revised:** Formalize bundle format spec + publisher CLI. **No consumer-side UI.** This is **bundle hygiene**, не marketplace. **Why bundle hygiene matters at N=1:** 1. **Java team handoff** требует documented manifest spec в любом случае — без этого new engineers не знают как добавить новый dict без полного code review pipeline 2. **Sales artifact** — demo prospects «ЦУОД bundle is independently signed/versioned, here's how you'd ship your own» без shipping консьюмерского UI 3. **Optionality** — когда customer #2 signs, bundle format уже defined, можно ship UI quickly (consumer UI = 5-7d incremental) **What this design explicitly is NOT:** - ❌ Browse catalog UI - ❌ Install dialog в admin-ui - ❌ Dry-run preview UI - ❌ Public marketplace - ❌ Bundle dep resolution / topological install - ❌ Multi-tenant Nexus namespacing **Anti-feature:** если scope expands beyond 2-3 days hard cap → STOP, re-design doc. Don't let founder weekend-prototyping pull this into Approach B by accident. --- ## Premises (validated через `/office-hours` 2026-05-12, including cross-model challenge) **P1.** Marketplace UI/registry **value scales с N customers.** At N=1 → near-zero. Build **only когда customer #2 LOI/contract стадия с extensibility language**. **P2.** Bundle **format + signing + manifest** valuable AT N=1 — separable concern от marketplace UI. Doubles as Java handoff spec + sales demo. **P3.** ЦУОД go-live (anchor v1) **уже live на v2.14.0 prod.** Дальнейший development must support handoff readiness, не speculative future features. **P4.** **No customer #2 named with deadline as of 2026-05-12.** Sales conversations ongoing (Альтум integration в process, гидрометео preliminary discussions). Marketplace UI build now = infrastructure ahead of validated need. **P5.** **«Defer entirely» (Approach A) was directionally right но oversold.** Cross-model challenge revealed: pure defer assumes founder won't drift to greenfield work. Pre-committed scoped C contains damage better than aspirational pure-defer. **P6.** **Bundle hygiene work ROI положителен независимо** от marketplace decision: даже если marketplace UI shipped'нется только в Q4 2026 или никогда — formal bundle spec нужен для Java handoff (target 2-3 months). **P7.** **Hard cap 2-3 days CC.** No scope creep. If пилот results in «we should add UI now», that's NEW design doc, new /office-hours, fresh decision. --- ## What ships в v2 (bundle hygiene, 2-3 days) ### 1. Bundle manifest format spec `ordinis-cuod-bundle/manifest.yaml` (NEW file, replaces ad-hoc Maven module structure): ```yaml apiVersion: ordinis.io/v1 kind: Bundle metadata: id: ru.cuod.dzz-ground-segment name: ЦУОД ДЗЗ — наземный сегмент version: 1.0.0 # semver, follows Maven artifact version description: | 40 dictionaries для управления наземным сегментом ДЗЗ: КА, типы КА, наземные станции, антенны, частотные диапазоны. domain: dzz scope: PUBLIC author: ЦУОД team license: proprietary signature: ed25519:base64... # added by publisher CLI dictionaries: # Existing list from ordinis-cuod-bundle/src/main/resources/bundles/cuod/ - name: spacecraft schemaVersion: 1.0.0 scope: PUBLIC schemaRef: dictionaries/spacecraft/schema.json # relative path sampleDataRef: dictionaries/spacecraft/sample.json # optional - name: satellite_type schemaVersion: 1.0.0 scope: PUBLIC schemaRef: dictionaries/satellite_type/schema.json # ... 38 more ``` **Migration:** Existing ad-hoc `ordinis-cuod-bundle/src/main/resources/bundles/cuod/` structure refactored to match manifest. **No behavior change** — bundle still loaded via existing Maven module pattern. Just **adds spec on top**. ### 2. Publisher CLI (`ordinis-bundle-publisher` Maven plugin) ```bash mvn ordinis:bundle-publish \ -Dbundle.path=ordinis-cuod-bundle \ -Dnexus.url=https://nexus.corp/ordinis-bundles/private/cuod \ -Dsigning.key=$BUNDLE_SIGNING_KEY ``` Steps плагина: 1. Read `manifest.yaml` 2. Validate каждый `schemaRef` is valid JSON Schema 7 via existing `SchemaValidator` 3. Compute bundle archive (tar.gz of manifest + schemas + sample data) 4. Sign archive с ed25519 key 5. Upload to corp Nexus с canonical path `//bundle.tar.gz` 6. Generate `bundle.sig` adjacent **Reuses:** existing Maven publish patterns в repo, corp Nexus credentials через GitLab CI variables. ### 3. Signature verification helper `BundleSignatureVerifier.java` в new module `ordinis-bundle-spec` (lightweight): ```java public class BundleSignatureVerifier { public boolean verify(byte[] archive, byte[] signature, PublicKey publicKey); } ``` **Не consumed в v2** (no consumer side). Built **as documentation artifact** для future marketplace work — defines verification contract. ### 4. Documentation `docs/user-guide/bundle-authoring.md`: - Bundle structure spec (manifest.yaml format) - How to publish (mvn command + Nexus setup) - Versioning semantics (semver, breaking change rules) - Schema authoring conventions reused from existing JavaDoc patterns `docs/integration/bundle-format-spec.md`: - Formal spec для Java team handoff - Manifest schema definition - Signing contract - Future consumer protocol (placeholder) --- ## What does NOT ship в v2 (explicit non-goals) | Feature | Why not | |---|---| | ❌ Admin UI «browse bundles» | No customer #2 with browse use case | | ❌ Install dialog в admin-ui | Customer-specific deployment = helm + values, не runtime install | | ❌ Dry-run preview UI | No install operation to preview | | ❌ Multi-tenant Nexus namespacing | N=1 customer, single namespace OK | | ❌ Dep resolution / topological install | Single bundle, no inter-bundle deps yet | | ❌ Public catalog | Customer #2+ + community curation = v3 | | ❌ Bundle uninstall flow | No install in admin UI → no uninstall | | ❌ Bundle update / migration scripts | Manual helm upgrade pattern remains | **Anti-feature commitment:** If during 2-3d implementation эти items появляются «just a bit more», STOP. Write new design doc, fresh /office-hours, fresh approval. --- ## Architecture ``` ordinis-cuod-bundle/ ordinis-bundle-spec/ (NEW module) ├── manifest.yaml ← NEW ├── BundleManifest.java ├── pom.xml ├── BundleSignatureVerifier.java └── src/main/resources/ └── pom.xml └── bundles/cuod/ ├── dictionaries/ ordinis-bundle-publisher/ (NEW Maven plugin) │ ├── spacecraft/ ├── BundlePublishMojo.java │ │ ├── schema.json ├── ManifestValidator.java │ │ └── sample.json └── pom.xml │ └── ... (39 more) └── (existing Maven structure) │ │ mvn ordinis:bundle-publish ▼ Corp Nexus ordinis-bundles/private/cuod/ └── ru.cuod.dzz-ground-segment/ └── 1.0.0/ ├── bundle.tar.gz └── bundle.sig ``` No new pods. No runtime changes к ordinis-app / ordinis-admin-ui. Only build-time tooling + Nexus artifacts. --- ## Approaches Considered ### Approach A — Defer entirely (0 days now) - **Pros:** Zero sunk cost. Capacity goes to AI metric work / prod hardening / customer #2 acquisition. - **Cons:** Java handoff still needs bundle format spec eventually — built later under deadline pressure. Pure defer ~20% adherence (cross-model challenge): founder likely drifts to greenfield marketplace prototyping anyway. ### Approach B — Full marketplace v1 (10-14 days, v1 doc original) - **Pros:** Real differentiator if customer #2 ships. Demo wow factor. - **Cons:** Infrastructure ahead of validated need. Spec drift между hypothetical и real customer #2 requirements. 10-14d sunk cost if N never grows. Triggers Brooks's «is this solving real problem или one we created?» ### Approach C-revised — **Bundle hygiene** (2-3 days, CHOSEN) - **Pros:** - Java handoff readiness (must-have anyway, due in 2-3 months) - Sales demo asset («signed versioned bundle artifact, here's our hygiene story») - Contains founder's marketplace energy в legitimate scope-bounded work - 5× cheaper than B, не «do nothing» of A - Future-leverage: when customer #2 needs UI, format already defined → UI 5-7d вместо 10-14d - **Cons:** - «Half feature» if framed as marketplace — мы НЕ frame'им так - Not consumer-visible (no UI screenshot for demo deck) - 2-3 days still > 0 days (Approach A); risk founder drifts beyond cap --- ## Recommended Approach: **C-revised — Bundle Hygiene** Rationale per `/office-hours` cross-model synthesis: 1. **Java handoff debt avoidance:** Manifest spec mandatory anyway when team scales beyond zimin.an. Build now while context fresh, cheaper than retro-spec under deadline. 2. **Sales conversation enablement:** Prospects asking «can we extend this с our own dictionaries?» get pointed at published bundle artifact + manifest spec — concrete answer без «we'll build it for you». 3. **Founder behavior containment:** Cross-model challenge правильно отметил: pure defer has ~20% follow-through odds. Pre-committed 2-3d scope легитимизирует bundle work, prevents weekend prototyping что expanded beyond bounds. 4. **Optionality preserved для customer #2:** If LOI signs Q3-Q4 — UI work spawn separate design doc, builds on this manifest, ships 5-7 days (smaller scope than ahead-of-time 10-14d). 5. **Engineering preference «explicit over clever»:** Manifest format defined upfront prevents implicit conventions, helpful for Java team handoff. --- ## Implementation plan | Step | Effort (CC) | Notes | |---|---|---| | 1. New module `ordinis-bundle-spec` (manifest POJO + verifier) | 3h | Pure Java, no Spring dep | | 2. New module `ordinis-bundle-publisher` (Maven plugin) | 4h | Standard Maven plugin scaffolding | | 3. `manifest.yaml` for `ordinis-cuod-bundle` (1.0.0 release) | 1h | Generated from existing bundle structure | | 4. Migrate ad-hoc bundle structure → match manifest paths | 2h | File moves, no logic change | | 5. Publisher CLI: tar.gz + ed25519 sign + Nexus upload | 4h | BouncyCastle for ed25519 | | 6. Manifest schema validation в publisher | 2h | Reuses existing SchemaValidator | | 7. GitLab CI integration (publish job on bundle tag) | 2h | New `.gitlab-ci.yml` job | | 8. Tests (publisher Mojo + verifier + manifest parse) | 4h | unit tests, no integration tests needed | | 9. `docs/user-guide/bundle-authoring.md` + `docs/integration/bundle-format-spec.md` | 3h | Java handoff artifact | | **Total** | **~25h (2-3 days CC)** | **Hard cap. No scope creep.** | **Anti-creep checkpoint:** After step 9, **STOP**. Don't add «just one consumer endpoint». Don't add «just a tiny browse list». Those are new design doc territory. --- ## Test plan | # | Test | Type | |---|---|---| | 1 | Manifest parser: valid YAML → typed object | unit | | 2 | Manifest validation: missing required field → error | unit | | 3 | Publisher Mojo: happy path → archive + signature generated | unit (Mojo) | | 4 | Publisher Mojo: invalid schemaRef → fail fast | unit | | 5 | Signature verifier: signed archive → returns true | unit | | 6 | Signature verifier: tampered archive → returns false | unit | | 7 | Signature verifier: wrong public key → returns false | unit | | 8 | Schema validation reuse: invalid JSON Schema в dict → publisher fails | unit | No integration / E2E tests — no runtime behavior changes. --- ## Open questions 1. **Where do signing keys live?** GitLab CI variables protected? Vault? Corp HSM? → Defer to ops decision при implement. 2. **Nexus namespace structure?** `ordinis-bundles/private////` — fine для v1. Multi-tenant adjustments в v2. 3. **Migration breaking?** Existing `ordinis-cuod-bundle` deployment relies on Maven module loaded at app startup. Manifest spec adds metadata, doesn't change loading. **Verify:** ordinis-app still loads bundle when manifest.yaml present но new spec module not on classpath (graceful degradation для existing v2.14.0 prod). --- ## Distribution plan Publisher Maven plugin distributed как corp internal artifact в Nexus. Authors add к their bundle's `pom.xml`: ```xml cloud.nstart.terravault.ordinis ordinis-bundle-publisher 1.0.0 ``` Then `mvn ordinis:bundle-publish` triggered by GitLab CI on tag push (e.g. `cuod-bundle-1.0.0`). Bundle.tar.gz uploaded к Nexus. No deployment changes к prod ordinis cluster — bundle archive consumed только by external authors / sales demos. --- ## Success criteria **Quantitative:** - Publisher Mojo completes < 60 sec на ЦУОД bundle (~40 dicts) - Signature verification < 10ms - Manifest validation catches 100% malformed manifests in unit tests **Qualitative:** - Java team handoff doc references `bundle-format-spec.md` as authoritative spec - Sales conversations с prospects use «signed versioned bundle» as differentiator - After 1 month: zero «founder drifted into consumer UI work» violations (scope cap held) **Failure criteria (rollback):** - Publisher Mojo bugs surface в > 2 releases of ordinis-cuod-bundle → reconsider as build-time vs separate plugin - No sales conversation uses bundle artifact within 3 months → format спека correct, distribution wrong (rare; spec stays anyway) --- ## What I noticed about how you think (during /office-hours) - **Initial position «build full marketplace» (v1 doc) → accepted «defer entirely» recommendation от me → accepted «bundle hygiene» revision после cross-model challenge.** Two reversals in one session = openness to push-back. Это редко — большинство founders defend original scope harder. - **«давай как рекомендуешь»** = trust calibrated на анализ + cross-model agreement. You didn't dismiss subagent challenge OR over-weight it — accepted synthesis as honest reading. - **Cross-model challenge value:** subagent found 4 things I missed (sales artifact, Java handoff, founder psychology drift risk, «treading water» mis-framing). Без cross-model call recommendation бы вышел overly conservative. **Session demonstrates value of /office-hours Phase 3.5 even когда первый instinct = skip it.** - **Anti-scope-creep pre-commitment** — `Hard cap 2-3 days. No scope creep.` line — это founder-level discipline, не engineering preference. Most founders write «target effort 2-3 days» что effectively unconstrained. --- ## Reviewer Concerns (Spec review skipped в этой session due to context length. Recommend `/plan-eng-review` separately когда implement starts, especially on:) - Module dependency graph (`ordinis-bundle-spec` standalone OK? circular dep risk если consumed by ordinis-app later?) - Nexus auth credentials lifecycle (GitLab CI vs Vault tradeoff) - Compatibility: existing prod v2.14.0 deployment should keep working без bundle-spec module --- ## See also - v1 SUPERSEDED (был «Dictionary Marketplace», full UI + registry + 10-14d). Reasoning for v1 → v2 revision lives в section «Approaches Considered». - Companion: `ai-schema-assist.md` — separate /office-hours design, AI assist authorship. **Sequencing:** AI assist baseline measurement (P5 prereq) before this. This work doesn't compete для bandwidth — separable. - Office-hours formal doc: `~/.gstack/projects/claude/zimin-main-design-bundle-hygiene-20260512.md` (cross-skill discoverable)