# Authoring a Bundle How to package справочники как distributable Ordinis bundle. См. также: [Bundle Format Specification](../integration/bundle-format-spec.md) — formal spec. --- ## Quick start ```bash # 1. Create bundle structure mkdir -p my-bundle/src/main/resources/bundles/my-id cd my-bundle # 2. Add at least one schema cat > src/main/resources/bundles/my-id/widget.schema.json <<'JSON' { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "x-id-source": "code", "required": ["code", "name"], "additionalProperties": false, "properties": { "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]{1,31}$", "x-unique": true }, "name": { "type": "object", "x-localized": true, "patternProperties": { "^[a-z]{2}-[A-Z]{2}$": { "type": "string" } }, "required": ["ru-RU"] } } } JSON # 3. Write manifest cat > manifest.yaml <<'YAML' apiVersion: ordinis.io/v1 kind: Bundle metadata: id: my-org.widgets name: My Widgets Bundle version: 1.0.0 scope: PUBLIC dictionaries: - name: widget schemaVersion: 1.0.0 scope: PUBLIC schemaRef: src/main/resources/bundles/my-id/widget.schema.json YAML ``` --- ## Versioning - `metadata.version` — semver. Patch на data fixes, minor на add'инге dict'ов, major на breaking schema changes. - `dictionaries[].schemaVersion` — per-dict semver, independent от bundle version. Bump когда меняется shape конкретной schema. - Breaking schema change (remove required field, change type, add `additionalProperties: false`) → MAJOR bump bundle. --- ## Validation locally ```bash # Через maven (если bundle — Maven artifact): mvn test -pl ordinis-bundle-spec -Dtest=CuodManifestFixtureTest # Или programmatically: import cloud.nstart.terravault.ordinis.bundle.spec.*; byte[] yaml = Files.readAllBytes(Path.of("manifest.yaml")); List errors = ManifestParser.parseAndValidate(yaml); if (!errors.isEmpty()) { errors.forEach(System.err::println); System.exit(1); } ``` --- ## Signing (production publish) Ed25519 keypair generation: ```bash openssl genpkey -algorithm Ed25519 -out signing-priv.pem openssl pkey -in signing-priv.pem -pubout -outform DER -out signing-pub.der ``` Sign bundle archive (until publisher Maven plugin lands — manual для now): ```java byte[] archive = Files.readAllBytes(Path.of("bundle.tar.gz")); byte[] privKey = Files.readAllBytes(Path.of("signing-priv.der")); // convert PEM→DER first String sig = BundleSignatureVerifier.sign(archive, privKey); // → patch manifest.yaml: metadata.signature: // OR write sidecar bundle.sig: ``` Public key распространяется к operators которые verify bundles перед install. --- ## Conventions ### Naming - `metadata.id` — reverse-DNS (`ru.cuod.dzz-ground-segment`, `com.acme.widgets`). - `dictionaries[].name` — snake_case (`spacecraft`, `ground_station`, `frequency_band`). ### Locales Localized fields (`x-localized: true`) — каждое значение это объект `{lang-COUNTRY: "..."}`: ```json "name": { "ru-RU": "Космический аппарат", "en-US": "Spacecraft" } ``` Bundle сам не объявляет supported locales — это per-dict. Manifest may add optional `metadata.locales` в future v1.x но spec строго ignores unknown сейчас. ### Foreign keys `x-references: "."` — backend validates на write. Если target dict в том же bundle — order ensured (см. consumer protocol §6 в spec). --- ## Anti-patterns - ❌ Не shipпите `additionalProperties: true` в production schemas — типизация теряется - ❌ Не используйте `$ref` к внешним URLs (security risk + offline build fail) - ❌ Не делайте 100+ dicts в одном bundle — расщепляйте по domain (e.g. `cuod-spacecraft`, `cuod-radio`) - ❌ Не bump'айте `schemaVersion` без реального schema change --- ## Handoff checklist (Java team) Когда передаёте bundle authoring к новой команде: 1. ✅ Прочитать [bundle-format-spec.md](../integration/bundle-format-spec.md) 2. ✅ Изучить `ordinis-cuod-bundle/manifest.yaml` как working example 3. ✅ Прогнать `mvn test -pl ordinis-bundle-spec` локально 4. ✅ Generate signing keypair, distribute pub key к ops 5. ✅ Set up CI publish job (когда `ordinis-bundle-publisher` plugin landed) Для вопросов: ordinis maintainers (см. CODEOWNERS).