339 lines
17 KiB
Markdown
339 lines
17 KiB
Markdown
# 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-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):
|
||
|
||
```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/<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`:
|
||
|
||
```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-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)
|