Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
greentic-bundle
greentic-bundle is now a small Rust workspace with a CLI crate and an in-repo read-only reader crate. PR-BUNDLE-01 established the command surface, embedded i18n, answer-document contract, and workspace layout. PR-BUNDLE-02 added the first real wizard orchestration path. PR-BUNDLE-02A replaces that flat form with a staged composition wizard for bundle creation and update: bundle basics, app-pack add/map loops, access-rule review, extension-provider selection, and a final build/dry-run/save-answers review step. PR-BUNDLE-03 added the first real authored-workspace mutation path for tenant/team gmap files and deterministic resolved-output sync. PR-BUNDLE-04 added a single catalog resolution/cache seam, real deterministic bundle.lock.json contents, offline replay from the workspace-local cache, and inspect output for the current lock state. PR-BUNDLE-05 added setup-spec and provider-QA form bridging plus bundle-owned composition-time setup persistence under state/setup/. PR-BUNDLE-06 added the first real build/export pipeline: normalized build state under state/build/, deterministic SquashFS .gtbundle output, and structured doctor / inspect reports for both workspaces and artifacts. PR-BUNDLE-06A makes crates/greentic-bundle-reader the typed read-only surface for built artifacts and normalized build directories.
Current baseline:
clap-based command surface forwizard,doctor,build,export,inspect,add,remove,access, andinit- embedded
i18n/en.jsoncatalog with locale normalization and fallback - semver-based
AnswerDocumentmodel and migration stub path - early workspace layout with
crates/greentic-bundle-reader - documented future contract that
buildwill become the.gtbundleSquashFS-producing command - wizard
run/validate/applyflow with deterministic plan output and replayable AnswerDocument JSON - real
access allow/access forbidmutations for tenant and team gmaps, including preview mode and generatedresolved/...sync - workspace-local catalog caching under
state/cache/catalogs - deterministic
bundle.lock.jsonwith catalog/app-pack/provider lock material inspect --root <DIR>output for the current bundle lock- setup bridging from legacy setup specs and provider QA payloads into normalized forms
- composition-time setup persistence under
state/setup/*.json - real SquashFS
.gtbundlebuild output - normalized build state under
state/build/<bundle>/normalized - structured
doctorandinspectreports for workspaces and built artifacts - real
init,add, andremovecommands for authored workspace initialization and dependency mutation - repo toolchain pinned to Rust 1.91 via
rust-toolchain.tomlandrust-version - embedded locale bundle covering the approved 66-locale set from
i18n/locales.json - translation validation/status tooling in
ci/i18n_check.py
CI and Releases
Local validation uses a single entrypoint:
This runs:
python3 ci/i18n_check.py validatepython3 ci/i18n_check.py statuscargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo test --all-featurescargo build --all-featurescargo doc --no-deps --all-features- crates.io packaging checks for every publishable crate in the workspace
For crates with workspace-internal publishable dependencies, local packaging verifies the source tree contract (Cargo.toml, src/, README, LICENSE, and runtime asset directories) and defers the real cargo package / cargo publish --dry-run to the release job after dependency crates have been published in order. This avoids false failures against crates.io for crates that depend on a sibling crate version not yet available in the public index.
GitHub Actions:
.github/workflows/ci.ymlruns lint, tests, and package dry-runs on pushes and pull requests..github/workflows/publish.ymlruns on pushes tomain/master(and manual dispatch), derivesvX.Y.Zfrom the primary crate version, skips itself when that version tag already exists, reruns the full local check on Linux, publishes crates to crates.io, builds sixcargo-binstallarchives, creates the GitHub release/tag, and pushes the archives to GHCR as OCI artifacts.- The publish workflow uses workspace dependency order and performs the real
cargo publish --dry-runfor dependent crates immediately before publish, after earlier workspace crates have already been released.
Release flow:
- Bump the version in
Cargo.toml. - Commit the change and push it to
mainormaster. publish.ymlderivesvX.Y.ZfromCargo.toml, creates that tag/release for the pushed commit, and skips publication if that version already exists.
Required secrets:
CARGO_REGISTRY_TOKENfor crates.io publishing.GHCR_TOKENfor GHCR publication ifGITHUB_TOKENis insufficient for package writes in the target repository settings.
Workspace Notes
The repo is intentionally a workspace already so the runtime-facing reader can live beside the authoring CLI. crates/greentic-bundle-reader now opens built .gtbundle SquashFS artifacts and normalized build directories, validates the basic manifest/lock contract, and exposes a stable typed runtime surface for bundle metadata, dependency refs, catalogs, resolved files, and setup-state files without leaking the on-disk layout into consumers. Because the main CLI depends on it at runtime, the reader crate is now a real publishable workspace crate rather than a private placeholder.
Current wizard behavior:
greentic-bundle wizardnow behaves like an interactive execute flow by default, so choosingCreate bundlewrites the workspace unless you explicitly use--dry-run.- The create/update wizard is now staged around real composition steps instead of a flat form.
- App packs are mandatory and are added one at a time with immediate
global/tenant/tenant/teammapping. - Mapping decisions are turned into gmap mutations and stored in
bundle.yamlasapp_pack_mappings. - Executed create/apply flows materialize app-pack
.gtpackfiles into the bundle layout:packs/for global scope,tenants/<tenant>/packs/for tenant scope, andtenants/<tenant>/teams/<team>/packs/for team scope. - Pack scope is handled inside the app-pack flow instead of a separate raw access stage; users choose scopes and the wizard generates gmap rules internally.
- Extension providers are added through a loop and are composition-only in this wizard; provider setup is not prompted here.
- Executed create/apply flows materialize extension-provider
.gtpackfiles intoproviders/<domain>/. greentic-bundle wizard run --mode updateasks for the current bundle root, loads the existingbundle.yaml, shows the current bundle values as editable defaults, and then re-enters the staged composition flow for packs and providers.greentic-bundle wizard runcollects a guided bundle composition interactively unless--answersis supplied.--dry-runcomputes a deterministic plan and emits answers without writing workspace files.greentic-bundle wizard validate --answers <FILE>rebuilds the normalized plan without side effects.greentic-bundle wizard apply --answers <FILE>replays the answers, initializes the workspace through the authored workspace model, and applies the mapped access grants for selected app packs.
Current access behavior:
greentic-bundle access allow <RULE>andgreentic-bundle access forbid <RULE>target eithertenants/<tenant>/tenant.gmaportenants/<tenant>/teams/<team>/team.gmap.- Access commands default to preview mode and print deterministic JSON describing the pending gmap mutation and generated resolved-output writes.
--executeapplies the gmap edit and reruns full deterministic resolution for the affected tenant/team, writingresolved/...andstate/resolved/....- Dry-run access previews do not create directories or touch workspace files.
Current catalog and lock behavior:
- Wizard execution resolves
remote_catalogsthrough a single catalog seam insrc/catalog/. - Local
file://...or workspace-local catalog paths are parsed, digested, and cached intostate/cache/catalogs/. - Offline replay works from the workspace-local cache via digest/ref index lookup.
bundle.lock.jsonnow records catalog refs/digests plus authored app-pack and extension-provider refs in deterministic order.- Remote non-file catalogs are centralized behind one client seam and now support a defined GHCR shorthand:
ghcr://catalogs/well-known[:tag|@sha256:...]maps toghcr.io/greenticai/catalogs/well-known[:tag|@sha256:...]and defaults to:latestwhen no tag/digest is supplied. oci://<registry>/<repo>[:tag|@sha256:...]is also accepted as the explicit remote format.- Remote GHCR/OCI catalogs now fetch through
greentic-distributor-clientand are cached back into the bundle workspace cache after resolution. - The checked-in source for the default public catalog is
packs/well-known.json. - Pushing a change to
packs/well-known.jsononmainormasternow runs.github/workflows/catalog.yml, which publishes bothghcr.io/greenticai/catalogs/well-known:sha-<commit>and:latest. - The catalog workflow now publishes with
GITHUB_TOKENand OCI source metadata so GHCR links the package back to this repository on first publish; package visibility still needs to be set toPubliconce in the GitHub Packages UI if anonymous pulls are required. - The repo now declares Rust 1.91 as its required toolchain, which aligns it with newer Greentic crate releases and supports the live distributor-client integration.
Current i18n behavior:
i18n/locales.jsonis the source-of-truth language list for the embedded locale bundle.- Locale selection precedence is
--locale, thenLC_ALL/LC_MESSAGES/LANG, then OS locale viasys-locale, thenen. - Locale normalization now accepts forms like
en_US.UTF-8,en_US,en-US, andde_DE@euro. - All locale JSON files are compiled into the binary by
build.rs; there is no runtime translation install step. tools/i18n.shis the repo entrypoint fortranslate,validate,status, andall.tools/i18n.sh translatenow passes an explicit--batch-size, controlled byBATCH_SIZEand defaulting to200.ci/i18n_check.py validateenforces key presence plus placeholder/newline/backtick invariants.ci/i18n_check.py statusreports missing/stale key counts per locale and now runs in local checks and CI.- The non-English locale files are currently seeded from
en.jsonso the repo has a complete embedded bundle and passing validation without depending on translator auth during development. Real translated content still needs a later authenticated translation-generation pass.
Current setup behavior:
- Setup normalization/persistence still exists for replayed answer flows, but provider setup is now intentionally absent from the create/update composition wizard.
- Catalog items may still carry inline setup metadata:
{"setup":{"type":"legacy","spec":{...}}}or{"setup":{"type":"provider_qa","qa_output":{...},"i18n":{...}}}. - Setup specs are normalized from either legacy setup documents or provider QA payloads into a bundle-local
FormSpecshape. - Execute mode writes deterministic setup state JSON to
state/setup/<provider>.json. - Dry-run and validate paths preview the same setup writes without persisting files.
- Setup persistence is bundle-owned and does not write to operator runtime or secrets-store paths.
Current build/export behavior:
buildcomputes a canonical build state frombundle.yaml,bundle.lock.json, resolved files, and setup state.- The normalized build state is written under
state/build/<bundle>/normalized. buildmaterializes a deterministic SquashFS.gtbundleartifact usingmksquashfs, defaulting todist/<bundle>.gtbundleinside the bundle root.exportcan rematerialize a.gtbundlefrom a normalized build directory, with--dry-runsupport.inspectanddoctoraccept either a workspace root or a built artifact and emit stable JSON.- Artifact-side inspection and validation now flow through
crates/greentic-bundle-readerrather than duplicatingunsquashfsparsing in the main crate. - Artifact/runtime metadata now carries
hooks,subscriptions, andcapabilitiesfrombundle.yamlinto the built manifest and reader surface. - Generated resolved manifests are now richer: they carry bundle metadata, catalog refs, authored extension providers, and per-target app-pack policy summaries.
Current authored mutation behavior:
initpreviews or creates a starter workspace withbundle.yaml,bundle.lock.json, tenant layout, and generated resolved outputs.add app-pack/add extension-providerupdatebundle.yaml, keepbundle.lock.jsonaligned, and rerender generated resolved outputs when executed.remove app-pack/remove extension-providerdo the inverse with the same preview-first JSON contract.
Key planned paths:
- authored workspace root:
bundle.yaml - future lock file:
bundle.lock.json - tenant gmaps:
tenants/<tenant>/tenant.gmap - team gmaps:
tenants/<tenant>/teams/<team>/team.gmap - generated resolved output:
resolved/...andstate/resolved/... - future setup-derived state:
state/setup/