Files
2026-05-12 17:05:24 +00:00

17 KiB
Raw Permalink Blame History

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):

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)

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-id>/<version>/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):

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

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/<customer>/<bundle-id>/<version>/ — 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:

<build>
  <plugins>
    <plugin>
      <groupId>cloud.nstart.terravault.ordinis</groupId>
      <artifactId>ordinis-bundle-publisher</artifactId>
      <version>1.0.0</version>
    </plugin>
  </plugins>
</build>

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-commitmentHard 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)