openalice-forge
[Atlas card](https://atlas.blal.pro/repos/openalice-forge)
Architecture rating
README has architecture diagram, env var table, endpoint table, quick-start — solid; AGENTS.md present; 25 named @feature annotations for Atlas ingestor; valid .atlas-deps.yml manifest; docs/flora-sota-research.md is substantial; ROADMAP-SOTA.md lists 47 items (0 completed); but no rustdoc module docs (224 missing docstrings), no dev workflow/test instructions, no contribution guide.
Atlas manifest valid, 25 @feature annotations across 13 files, zero circular deps, consistent Result<_,String> error pattern; but inspector flags 15 god modules, max cyclomatic complexity 77, 22 complexity flags, 160 format issues, 11 long param lists, 10 duplicate signatures, 29 'any' type usages in dashboard TS, 6 missing React key props — code quality debt undermines the good structural conventions.
SQLite with FK constraints ON, WAL journal, 4 indexes — adequate for single-tenant asset store; but zero migration system (CREATE TABLE IF NOT EXISTS on every boot — ALTER TABLE requires manual intervention); single Mutex<Connection> serializes all writes; INSERT OR REPLACE on asset_files/jobs silently overwrites; no tenant isolation (by design); no PII stored so GDPR is N/A.
46 tests total (41 #[test] unit + 5 #[tokio::test] route integration via tower::oneshot); covers core geometry math and key API routes; CI workflow exists but latest run FAILED (2026-06-17); zero coverage tooling (no tarpaulin/llvm-cov); zero dashboard tests (31 TS/TSX source files untested); no tests/ directory — all inline #[cfg(test)] only.
Auth entirely optional when FORGE_SECRET_KEY unset; download_mesh handler has unguarded path traversal (main.rs:973); secret key accepted via ?key= query param (leaks to logs/history); allow_origin(Any) CORS on all routes incl. writes; zero rate limiting; no security headers (CSP/HSTS/X-Frame); Docker runs as root with no Dockerfile present; parameterized SQL and file_preview canonicalize check are the only positives.
Structured JSON logging via tracing-subscriber is properly configured (main.rs:1055); /health endpoint returns DB stats and uptime; but zero Prometheus metrics/counters/histograms, no /metrics endpoint, no #[tracing::instrument] spans, no OpenTelemetry exporter, no liveness vs readiness probe distinction — effectively log-only observability.
SIGTERM not handled — only tokio::signal::ctrl_c(), so Docker hard-kills after stop timeout (main.rs:1101); no timeout on reqwest HTTP client; no retry/backoff logic anywhere; Mutex::lock().unwrap() in all 11 DB methods — mutex poison crashes the process; approve/generate endpoint returns 501 stub; no idempotency keys on POST endpoints.
source · auto-grader-2026-06-18
Ecosystem manifest
.atlas-deps.ymlAsset factory for procedural world generation — NanoBanana texture gen, tree space-colonisation, PBR planner, VRM/GLTF export, SQLite store, cost ledger.
- via cargoShared axum + tracing + reqwest plumbing pulled in as a Cargo crate at build time.
- gemini-apihttpoptionalvia OPENROUTER_API_KEYPBR planner uses Gemini via OpenRouter to draft material parameters before texture generation.
- nanobanana-apihttpoptionalvia NANOBANANA_API_URLCalls NanoBanana 2 (OpenRouter — google/gemini-3.1-flash-image-preview) to generate PBR textures and sprites after operator approval.
- PORT
- FORGE_DATA_DIR
- FORGE_SECRET_KEY
- FORGE_TEXTURES_DIR
- NANOBANANA_API_URL
- OPENROUTER_API_KEY
- http_endpoint: https://forge.blal.pro/v1/*
- docker_image: openalice-forge-api
- categories
- asset_definitions
- asset_files
- world_templates
- generation_jobs
- cost_log
Atlas grepped the repo's source for env reads (rust env::var · ts process.env · py os.environ · shell $VAR) and diffed against the manifest's consumes_env. Two lists below: stale declarations and undeclared reads.
- DOMAIN
- NANOBANANA_API_URL
- OPENROUTER_API_KEY
- PORT
Code composition
tokei · loc- Rust76.4%
- TSX19.5%
- TypeScript1.1%
- CSS1.0%
- JSON0.8%
- Other1.2%
- Rust76.4%
- TSX19.5%
- TypeScript1.1%
- CSS1.0%
- JSON0.8%
- Other1.2%
- Rust76.4%· 9,201
- TSX19.5%· 2,348
- TypeScript1.1%· 130
- CSS1.0%· 125
- JSON0.8%· 97
- YAML0.6%· 76
- HTML0.2%· 26
- TOML0.2%· 23
- +2 more0.2%· 25 · 7 files
| Language | % code | code | comments | blanks | files |
|---|---|---|---|---|---|
| Rust | 76.4% | 9,201 | 720 | 692 | 17 |
| TSX | 19.5% | 2,348 | 62 | 229 | 26 |
| TypeScript | 1.1% | 130 | 27 | 21 | 5 |
| CSS | 1.0% | 125 | 0 | 5 | 1 |
| JSON | 0.8% | 97 | 0 | 0 | 3 |
| YAML | 0.6% | 76 | 6 | 5 | 3 |
| HTML | 0.2% | 26 | 0 | 1 | 1 |
| TOML | 0.2% | 23 | 0 | 2 | 1 |
| JavaScript | 0.2% | 20 | 2 | 3 | 2 |
| SVG | 0.0% | 5 | 0 | 0 | 5 |
| Markdown | 0.0% | 0 | 276 | 101 | 7 |
Telemetry ribbon · last 90 days
4 eventsforge/api
1 feature- forge.api.authsrc/main.rs:1@feature forge.api.dashboard — Embedded static HTML dashboard served at / for browsing registry + triggering generations without a CLI. @feature forge.api.file-preview — Sandboxed asset file preview (GET /v1/files/:id/preview) with double path-traversal guard: id alphabet check + canonicalize-within-data-dir assertion. OpenAlice Forge — Asset Factory for procedural world generation. API: GET /health — service health + stats GET /v1/registry/categories — list categories GET /v1/registry/assets?category=... — list assets in category GET /v1/registry/assets/:id — get asset definition GET /v1/registry/search?q=... — search assets GET /v1/costs — spending summary
forge/batch
1 feature- forge.batch.mocksrc/main.rs:412Run every registered asset through the mock generator pipeline (planning + dry-run).api:POST /v1/batch/mocksince 0.1.0
forge/characters
2 features- forge.characters.generate-allsrc/main.rs:737Procedurally generate all VRM character texture sets (free, no external APIs).api:POST /v1/characters/generate-allsince 0.1.0
- forge.characters.texture-plansrc/generators/character.rs:1@feature forge.characters.presets — Seeded character presets (Knight, Elf Mage, Villager) used as quick-start palette for VRM avatar customization without manual config. Scaffold module — character texture pipeline lives behind a feature flag. ![allow(dead_code)] Character Factory — VRM-compatible texture generation. Generates face, hair, outfit textures for VRM avatar customization. NOT generating VRM meshes (VRoid Studio limitation) — only textures. VRM UV layout slots: - Face: eyes, mouth, skin tone, markings - Hair: color, highlights, style details - Body/Outfit: armor, robe, casual, accessories Character = combination of face + hair + outfit textures.
forge/dashboard
2 features- forge.dashboard.mesh-previewdashboard/src/components/forge/MeshPreview.tsx:40Standalone Three.js GLB viewer for inspecting a single forge mesh in the dashboard.class:MeshPreviewsince 0.1.0
- forge.dashboard.scene-previewdashboard/src/components/forge/ScenePreview.tsx:137Three.js viewer that instances meshes per InstanceGroup transforms to render a forge scene.class:ScenePreviewsince 0.1.0
forge/generate
1 feature- forge.generate.approvesrc/main.rs:333Approval endpoint for a planned job — currently GATED. The Forge is dry-run/mock only (no paid API calls without an explicit, not-yet-built approval gate), so this honestly returns 501 instead of leaving the URL the plan/mock messages advertise as a dead 404.api:POST /v1/generate/approve/:job_idsince 0.1.0
forge/material
2 features- forge.material.pbr-plannersrc/generators/material.rs:1Wired into HTTP via POST /v1/materials/plan (main::plan_material). Not yet wired into the mesh pipeline. PBR Material generator — albedo + normal + roughness maps. A PBR material = 3 textures generated from ONE description: 1. Albedo (color/diffuse) — base color texture 2. Normal map — surface bumps and detail 3. Roughness map — shiny vs matte areas For anime style: normal maps are subtle, roughness is mostly flat. Realistic: full PBR with detailed normals and roughness variation.
- forge.material.plansrc/main.rs:212Dry-run a PBR material set — fan one description into albedo + normal + roughness map prompts with per-map cost accounting (no API call).api:POST /v1/materials/plansince 0.1.0
forge/mesh
3 features- forge.mesh.flora-primitivessrc/generators/flora.rs:1Extra flora primitives — mushrooms, ferns, lily pads, lavender, rose bushes, ivy, cactus, crystal clusters. Each generator emits one or more [`MeshData`] objects sized to ~30 cm – 1 m so they drop into the existing scene scatter at sensible per-instance scale ranges. Wind-aware variants apply the foliage shader pivot/wind attributes the same way trees do.
- forge.mesh.procedural-glbsrc/generators/mesh.rs:1@feature forge.mesh.wind-attributes — Per-vertex wind weight + phase (TEXCOORD_1) and pivot/pivot2 custom attributes exported into GLB for two-level foliage shader animation. Procedural mesh generator — FREE, no API calls. Generates low-poly 3D meshes for game assets: - Trees (trunk cylinder + leaf sphere/cone) - Rocks (noise-displaced icosahedron) - Bushes (cluster of spheres) - Props (barrel, crate, fence post) Output: raw vertex/index data, exported to GLB via glTF.
- forge.mesh.tree-space-colonizationsrc/generators/tree.rs:1Space Colonization tree generator. Algorithm: 1. Scatter attraction points in a crown envelope (sphere/ellipsoid) 2. Find nearest branch node for each attractor 3. Grow branches toward attractors 4. Remove attractors that are too close to branches 5. Repeat until no attractors remain 6. Generate cylinder mesh for each branch segment 7. Add leaf billboard quads at branch tips Based on: "Modeling Trees with a Space Colonization Algorithm" (Runions, Lane, Prusinkiewicz, 2007)
forge/meshes
1 feature- forge.meshes.generate-allsrc/main.rs:790Procedurally generate all GLB meshes (trees, props, terrain) free of external API cost.api:POST /v1/meshes/generate-allsince 0.1.0
forge/pipeline
2 features- forge.pipeline.mock-executesrc/pipeline/mod.rs:1@feature forge.pipeline.job-tracking — Generation jobs persisted to SQLite with status progression (running → completed_mock / accepted / rejected); jobs queryable via GET /v1/generate/jobs. Generation pipeline — plan → approve → generate → review. Debug mode: logs every step, mock generates placeholder images.
- forge.pipeline.placeholder-gensrc/generators/placeholder.rs:1Scaffold module — placeholder helpers used by the mock generation flow only. ![allow(dead_code, unused_variables)] Placeholder image generator — colored PNGs for mock mode. Creates visually distinct placeholders per category so you can see what WOULD be generated without spending tokens.
forge/registry
4 features- forge.registry.list-assetssrc/main.rs:128List asset definitions for a registry category (terrain, character, prop, scene...).api:GET /v1/registry/assetssince 0.1.0
- forge.registry.palettessrc/registry/palettes.rs:1World Palettes — biome-to-asset mapping. A palette defines which assets are used in each biome, so openalice-world can fetch the right textures/sprites.
- forge.registry.searchsrc/main.rs:161Free-text search across registered asset definitions.api:GET /v1/registry/searchsince 0.1.0
- forge.registry.taxonomysrc/registry/mod.rs:1@feature forge.registry.asset-definitions — ~55 default asset definitions seeded at boot covering terrain/flora/structures/characters/materials with generation prompts + biome mappings. Asset registry — categories + definitions + taxonomy seeding.
forge/scenes
2 features- forge.scenes.composesrc/scenes.rs:1@feature forge.scenes.instance-groups — Batched instance transform format ([x,y,z,rot_y,scale] per entry) cuts scene JSON ~5× vs per-key objects; maps 1:1 to Three.js InstancedMesh for single-draw-call rendering. Scene composition — JSON specs describing a placed-asset world. A `SceneSpec` lists a biome, lighting, fog, ground material, and a flat array of `Placement` records pointing at GLBs from `/v1/meshes/`. The world engine (or the dashboard preview) loads the JSON, fetches each referenced GLB, and instantiates them at the given transforms. Placement uses a simple "best-candidate" Poisson-disk-ish sampler: tries N random points per slot, picks the one furthest from any existing placement and above the type's `min_dist`. Cheap, gives a natural-looking scatter without true Poisson cost.
- forge.scenes.generate-allsrc/main.rs:836Build six demo scenes — JSON specs composing mesh GLBs into playable showcase environments.api:POST /v1/scenes/generate-allsince 0.1.0
forge/sprite
2 features- forge.sprite.billboard-gensrc/generators/sprite.rs:1Wired into HTTP via POST /v1/sprites/plan (main::plan_sprite) as a dry-run planner. The alpha post-process pipeline ships when generation goes live. Sprite generator — billboards with alpha transparency. Sprites are 2D images with transparent background used as billboards in 3D (trees, bushes, particles, UI icons). Post-processing pipeline: 1. Generate via NanoBanana with alpha prompt 2. Extract alpha channel (threshold-based) 3. Trim transparent borders (auto-crop) 4. Validate: min opacity area > 10% (not empty)
- forge.sprite.plansrc/main.rs:237Dry-run a sprite/billboard generation — return the alpha-optimized prompt, single-call cost, and the alpha post-process pipeline (no API call).api:POST /v1/sprites/plansince 0.1.0
forge/store
1 feature- forge.store.sqlitesrc/store/mod.rs:1@feature forge.store.cost-ledger — Generation cost ledger: every real API call records tokens + USD spend; GET /v1/costs returns rolling summary for budget tracking. Persistent SQLite store for asset registry, files, jobs, and costs.
forge/texture
3 features- forge.texture.nanobanana-gensrc/generators/texture.rs:1@feature forge.texture.prompt-builder — Style-aware prompt construction (anime/lowpoly/realistic) with tileable-seam and alpha-isolation clauses baked in automatically. Scaffold module — wired up later when NanoBanana generation goes live. ![allow(dead_code, unused_variables)] Texture generator via NanoBanana 2 (Gemini Flash Image Preview). Prompting best practices (from Google + community guides): - Be specific: lighting, texture quality, color palette - State resolution explicitly: "1024x1024" - For tileable: "seamless tileable texture, repeating pattern" - For anime: "anime style, cel-shaded, flat colors, clean lines" - For sprites: "alpha transparent background, centered, top-down view" - Stack requirements: model handles nuance well - Reference real styles: "Studio Ghibli style", "Genshin Impact aesthetic"
- forge.texture.plansrc/main.rs:185Dry-run a texture generation — return prompt, settings, and cost estimate (no API call).api:POST /v1/textures/plansince 0.1.0
- forge.texture.procedural-florasrc/generators/texture_gen.rs:1@feature forge.texture.tree-atlas — 512×512 RGBA atlas packing bark + leaf + needle into one GLB image slot; one material per tree type, shared across all instances. Procedural alpha texture generation for WoW-style flora. Generates PNG textures with alpha channel for: - Leaf cluster cards (canopy of small leaves on a single quad) - Single leaf shapes (oval, diamond, star, blossom, needle, fan) - Grass blade silhouette Output: RGBA8 PNG, sized 256×256 by default. Cached on disk so we generate once and re-use across all GLBs.
forge/vrm
1 feature- forge.vrm.procedural-texturessrc/generators/vrm.rs:1@feature forge.vrm.preset-library — Five built-in presets (Knight, Elf Mage, Villager, Dark Warrior, Forest Elf) cover armor/robe/casual outfit archetypes for immediate world population. Scaffold module — full VRM pipeline ships with the character system. ![allow(dead_code)] VRM Character Texture Factory — procedural textures for VRM avatars. Generates face, hair, outfit textures as colored PNGs. No API calls — pure procedural image generation via `image` crate. openalice-world has base VRM models (male.vrm, female.vrm). We generate textures to apply on them for character customization.