Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ASO — Agnostic Spatial Objects

ASO is a compact production MVP for immutable spatial-object identity, publication, discovery, integrity, and world composition. The npm-workspaces monorepo contains a Next.js App Router web/API service in apps/web and the browser/Node SDK in packages/sdk.

Production origins:

  • Application and API: https://aso.ai3d.dev
  • Immutable asset origin: https://ooo.ai3d.dev
  • OpenAPI: https://aso.ai3d.dev/api/v1/openapi.json

Both custom hostnames map directly to Cloud Run with Google-managed TLS; no global IP or external load balancer is used.

Run locally

Requires Node 22 and npm 10.

npm install
npm run setup:genblaze
npm run dev
npm test
npm run typecheck
npm run build

With no database, development and next build use a deterministic demo catalog: two immutable versions of one glTF object, one unsupported PLY object, and a world pinning all three exact versions. Production runtime never falls back to demo data; /api/v1/health returns 503 when persistence is absent. Set DATABASE_URL, run npm run db:migrate, and start the service for production.

Configuration

Canonical variables are documented in .env.example. Aliases are accepted only for compatibility:

  • NEON_URL → canonical DATABASE_URL
  • B2_BUCKET → canonical B2_PUBLIC_BUCKET
  • GOOGLE_PROJECT_ID or GOOGLE_CLOUD_PROJECT → canonical Firebase Admin FIREBASE_PROJECT_ID
  • GOOGLE_PROJECT_ID in .env is authoritative for Firebase and Google Cloud deployment. GOOGLE_CLOUD_PROJECT is an optional alias and must match when set.

B2 uses its S3-compatible endpoint. Public versions are written under identity/version-scoped, cache-immutable keys; a distinct private staging bucket is recommended. GenBlaze uses REPLICATE_API_TOKEN with the pinned genblaze-replicate provider to generate reference images; genblaze-s3 writes each generated image and tamper-evident run manifest directly to the configured B2 public bucket before ASO copies and verifies the image under its immutable object identity. GENBLAZE_IMAGE_MODEL defaults to black-forest-labs/flux-2-klein-4b for near-real-time reference generation; black-forest-labs/flux-schnell remains available as a fallback. Firebase Admin validates publisher ID tokens. For local development only, publication also accepts x-api-key: local-development-key. PUBLICATION_API_KEY_SECRET enables a separately managed production API key. Firebase browser config consists only of NEXT_PUBLIC_FIREBASE_* public values and is gracefully omitted when unset.

API and SDK

API root: /api/v1; machine-readable contract: /api/v1/openapi.json; interactive usage guide: /docs.

import { ASOClient, verifyIntegrity } from '@aso/sdk';

const aso = new ASOClient({ baseUrl: 'https://aso.ai3d.dev/api/v1' });
const page = await aso.listObjects({ q: 'chair', tag: 'furniture', limit: 20 });
const object = await aso.getObject(page.items[0].id, page.items[0].version);
const representation = object.representations[0];
const bytes = await aso.fetchRepresentation(representation);
if (!await verifyIntegrity(bytes, representation.hash)) throw new Error('integrity failure');

Publication

POST /publish/objects accepts either:

  1. multipart/form-data with metadata (JSON containing a representation descriptor) and asset,
  2. JSON { metadata, sourceUrl } for bounded server fetch, or
  3. JSON { metadata, stagedKey } after direct staging.

ASO is representation-agnostic. glTF/GLB bytes receive structural and descriptor validation. The publish UI recognizes common mesh formats (OBJ, FBX, STL, 3MF, COLLADA, and USD variants), point-cloud formats (PLY, PCD, LAS, LAZ, and XYZ), and Gaussian-splat formats (SPLAT, SPZ, and KSPLAT). These and other safe declared formats are stored as opaque bytes: ASO validates the format token and media type, enforces the 100 MiB bound, computes the real sha256-<base64> integrity and byte length, and reports runtime incompatibility honestly rather than claiming renderability. Recognition supplies editable metadata defaults; it does not imply structural validation or browser preview support.

For direct staging, POST { "mediaType": "application/octet-stream" } to /publish/staging, PUT bytes to the returned uploadUrl with its exact headers, then submit the returned key as stagedKey. Signed URLs expire after 15 minutes. URL sources must use public HTTPS, cannot resolve to private/link-local addresses, cannot redirect, time out after 30 seconds, and cannot exceed 100 MiB. Every flow writes immutable keys and rejects duplicate (id, version) records.

World publication validates every pinned object ID, version, and canonical manifest URL before insertion. Existing versions are never updated. Metadata discovery supports full-text query, tags, license, representation type/format, generator, runtime, sorting, opaque cursors, and bounded limits.

Canonical versioned schemas are:

  • /schemas/aso.object.v0.1.schema.json
  • /schemas/aso.world.v0.1.schema.json
  • /schemas/aso.agent-object.v0.1.schema.json
  • /schemas/aso.agent-world.v0.1.schema.json

The older unversioned schema URLs remain compatibility aliases.

const metadata = {
  schema: 'aso/object/v0.1', id: 'studio-chair', version: '1.0.0',
  name: 'Studio chair', description: 'Portable chair mesh', tags: ['furniture'],
  createdAt: new Date().toISOString(), provenance: { adapter: 'example@1' },
  representation: { id: 'primary', type: 'mesh', format: 'glb', mediaType: 'model/gltf-binary' }
};
const form = new FormData();
form.set('metadata', JSON.stringify(metadata));
form.set('asset', file);
await fetch('/api/v1/publications', { method: 'POST', headers: { authorization: `Bearer ${firebaseIdToken}` }, body: form });

The browser provider downloads GLB/glTF on demand, parses basic structure, and verifies content integrity. It intentionally reports diagnostics and a download link rather than claiming a full 3D render when no renderer or compatible asset is available.

Verified production status

As of August 3, 2026, the current Cloud Run revision serves 100% of traffic. Both direct custom-domain mappings report ready/routable with Google-managed certificates. Neon migrations 0000 and 0001 are applied, Firebase Email/Password and Google providers are enabled, and the production catalog persistently contains demo-chair@1.0.0, demo-chair@1.1.0, demo-point-cloud@1.0.0, and demo-version-gallery@1.0.0.

Validation passes 48 unit tests (30 web + 18 SDK), workspace typecheck, production build, 5 local Chromium E2E tests, 5 public-domain Chromium E2E tests, and production smoke checks. Known MVP limitations: non-glTF representations are integrity-verified opaque bytes until a runtime provider supports them; direct Cloud Run domain mappings do not provide fixed IP/CDN/Cloud Armor; and Backblaze B2 does not support S3 conditional PUT, so publication uses database/key preflight checks rather than an atomic If-None-Match write.

Operations

  • npm run validate: unit tests, workspace typecheck, and production build.
  • npm run test:e2e: Chromium browser coverage for browse/search, exact versions, viewer/fallback, manifests, agents, worlds, schemas, and publication authorization. Set E2E_BASE_URL=https://aso.ai3d.dev for public-domain verification.
  • npm run db:migrate: apply Drizzle migrations (0000_initial.sql and 0001_persistence_repository.sql).
  • npm run seed:production: idempotently publish the persistent demo catalog through the public authenticated API. It verifies matching existing immutable bytes and fails on mismatches; it never prints the API key.
  • npm run smoke:gcp: verify both custom HTTPS origins, readiness, OpenAPI/schemas, demo histories, agent/integrity routes, B2-proxied bytes and hashes, reverse world references, and unauthenticated publication rejection.
  • npm run deploy:gcp: use .env's authoritative GOOGLE_PROJECT_ID, run Cloud Build, deploy the resulting immutable image tag to Cloud Run, and execute public smoke checks.
  • npm run deploy:cloud-run: deploy an already-built IMAGE; it binds REPLICATE_API_TOKEN from the Cloud Run Secret Manager secret named by REPLICATE_SECRET_NAME (default replicate-api-token) and never reads token values from .env. The Cloud Run service account must have roles/secretmanager.secretAccessor.

Firebase Admin uses Cloud Run Application Default Credentials. Before browser sign-in can work, initialize Firebase Authentication, enable Email/Password and Google, choose a Google support email, and authorize aso.ai3d.dev. Browser SDK values are public configuration, not service-account secrets.

Direct Cloud Run domain mappings require these DNS records:

  • aso CNAME ghs.googlehosted.com.
  • ooo CNAME ghs.googlehosted.com.

Wait for each mapping to report Ready=True before relying on Google-managed TLS. Introduce a global external Application Load Balancer only if fixed IP, Cloud CDN, Cloud Armor, multi-region, or multi-backend routing becomes necessary.

GenBlaze reference-image generation is an authenticated, synchronous publication workflow at POST /api/v1/generate and in the /generate UI. The user supplies a subject prompt and the worker deterministically sends an isometric 3d model of … to FLUX.2 Klein while preserving both source and effective prompts in provenance. It runs Replicate through the official GenBlaze Python SDK, persists the original generated image and GenBlaze provenance manifest to B2, reads the stored image back through the B2 provider, verifies GenBlaze's byte length and SHA-256 when present, and publishes a second identity/version-scoped ASO copy with the GenBlaze run, model, prompt, manifest, and source asset recorded in provenance. The resulting image is a normal immutable ASO object and can be attached as the exact reference-image input when publishing a downstream 3D object. Configure REPLICATE_API_TOKEN for local development only. Production must bind the token from Secret Manager to Cloud Run as REPLICATE_API_TOKEN; deployment scripts never copy secret values from .env into revision configuration. The generation endpoint accepts only the two explicitly supported model identifiers, applies server-side authentication, and treats prompts and generated metadata as public immutable content.

Install, tests, validation, build, and seed dry reads do not mutate infrastructure. Authenticated generation and publication requests intentionally write immutable artifacts to B2 and registry records to persistence.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages