Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
{"id":"openforge_catalog-5gb","title":"Frontend: Admin camera position controls UI","description":"Build admin interface to preview and set default camera angles for models. Shows live preview of each angle, allows selecting which is default. Integrates with admin set camera position API. Consider batch operations for setting defaults across similar models.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-21T09:58:45.023938263-07:00","updated_at":"2025-12-21T09:58:45.023938263-07:00","dependencies":[{"issue_id":"openforge_catalog-5gb","depends_on_id":"openforge_catalog-bll","type":"parent-child","created_at":"2025-12-21T09:59:19.862145404-07:00","created_by":"daemon"},{"issue_id":"openforge_catalog-5gb","depends_on_id":"openforge_catalog-hqe","type":"blocks","created_at":"2025-12-21T09:59:36.561390068-07:00","created_by":"daemon"}]}
{"id":"openforge_catalog-5na","title":"Phased rollout: Test subset before bulk backfill","description":"Implement safe migration strategy: (1) Generate sprite sheets for small test set (~10-20 diverse models). (2) Deploy frontend with fallback to legacy single thumbnails. (3) Validate with users - test interactive controls, image quality, performance. (4) Iterate on camera positions/layout based on feedback. (5) Only after validation, run bulk backfill for all 8000+ STL files. Include ability to pause/resume bulk processing. Track which models have sprite sheets vs legacy thumbnails.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-21T10:13:57.517770238-07:00","updated_at":"2025-12-21T10:13:57.517770238-07:00","dependencies":[{"issue_id":"openforge_catalog-5na","depends_on_id":"openforge_catalog-bll","type":"parent-child","created_at":"2025-12-21T10:14:18.760726353-07:00","created_by":"daemon"},{"issue_id":"openforge_catalog-5na","depends_on_id":"openforge_catalog-4ji","type":"blocks","created_at":"2025-12-21T10:14:23.673079682-07:00","created_by":"daemon"},{"issue_id":"openforge_catalog-5na","depends_on_id":"openforge_catalog-3cx","type":"blocks","created_at":"2025-12-21T10:14:24.071569003-07:00","created_by":"daemon"},{"issue_id":"openforge_catalog-5na","depends_on_id":"openforge_catalog-dd4","type":"blocks","created_at":"2025-12-21T10:14:24.494018624-07:00","created_by":"daemon"}]}
{"id":"openforge_catalog-5tg","title":"Backend API: Get thumbnail variants endpoint","description":"Create Flask endpoint to return sprite sheet info for a model. Returns: (1) Sprite sheet URL, (2) Grid layout (rows, cols, tile dimensions), (3) Angle metadata (name, position in grid, camera coords), (4) Default angle index. Frontend uses this to display correct region from sprite sheet. Handles models with legacy single thumbnail gracefully.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T09:58:32.287223899-07:00","updated_at":"2025-12-21T14:00:25.231595972-07:00","closed_at":"2025-12-21T14:00:25.231595972-07:00","close_reason":"Completed: Created GET /api/blueprints/\u003cblueprint_id\u003e/thumbnail-variants endpoint. Returns sprite sheet URL, grid layout (rows/cols/tile_size), angle metadata with camera positions, and default angle index. Gracefully handles legacy single thumbnails. All 319 tests passing.","dependencies":[{"issue_id":"openforge_catalog-5tg","depends_on_id":"openforge_catalog-bll","type":"parent-child","created_at":"2025-12-21T09:59:18.52350897-07:00","created_by":"daemon"},{"issue_id":"openforge_catalog-5tg","depends_on_id":"openforge_catalog-ubp","type":"blocks","created_at":"2025-12-21T09:59:35.26824895-07:00","created_by":"daemon"}]}
{"id":"openforge_catalog-750","title":"Postgres migration: thingiverse sync-state tables","description":"New schema version adding: thingiverse_thing (blueprint_id \u003c-\u003e thing_id, status, published_at, last_synced_at) and thingiverse_file (thing ref, catalog file ref + local hash, remote file id + remote hash, last_synced_at) — the diff ledger for the sync engine. Follow existing openforge/db/schema/version_NN.py migration pattern. If the HAR ticket proves the remote hash is SHA-256 (catalog stores MD5), include storage for the second hash algorithm.","notes":"SCOPE NOTES: (1) thingiverse_file must carry a file-type/role discriminator (model/image/zip/other) since things contain mixed file types. (2) This runs against the LOCAL db; prod gets a subset via the fixture path (see openforge_catalog-8yb) — keep the mapping (blueprint_id, thing_id, public_url) cleanly separable from local-only operational state (hash ledger, sync timestamps).","status":"open","priority":2,"issue_type":"task","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:42:25.104764326-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T11:55:49.425508213-06:00","dependencies":[{"issue_id":"openforge_catalog-750","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:42:52.476138903-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-750","title":"Postgres migration: thingiverse sync-state tables","description":"New schema version adding: thingiverse_thing (blueprint_id \u003c-\u003e thing_id, status, published_at, last_synced_at) and thingiverse_file (thing ref, catalog file ref + local hash, remote file id + remote hash, last_synced_at) — the diff ledger for the sync engine. Follow existing openforge/db/schema/version_NN.py migration pattern. If the HAR ticket proves the remote hash is SHA-256 (catalog stores MD5), include storage for the second hash algorithm.","notes":"SCOPE NOTES: (1) thingiverse_file must carry a file-type/role discriminator (model/image/zip/other) since things contain mixed file types. (2) This runs against the LOCAL db; prod gets a subset via the fixture path (see openforge_catalog-8yb) — keep the mapping (blueprint_id, thing_id, public_url) cleanly separable from local-only operational state (hash ledger, sync timestamps).","status":"in_progress","priority":2,"issue_type":"task","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:42:25.104764326-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T14:40:56.467812707-06:00","dependencies":[{"issue_id":"openforge_catalog-750","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:42:52.476138903-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-7dg","title":"Auth/token manager for Thingiverse v2 (login + refresh)","description":"Python module: interactive 'login' does POST /v2/auth/login {usernameOrEmail, password} -\u003e AuthTokensResponse (handle 202 2FA via /v2/auth/2fa/login), persists refresh token securely (env file/keyring, never in repo); runtime path auto-refreshes access JWT via POST /v2/auth/refresh. Password is never stored. Buildable and testable today against the live API — verify a Devon-scoped JWT via GET /v2/users/me. Note: THINGIVERSE_APP_TOKEN in ~/.profile.d/099.api_keys.sh is v1-only and scoped to the wrong account (Joaquin Munguia, id 5577639) — do not use.","status":"closed","priority":1,"issue_type":"feature","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:42:24.708129858-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T14:39:30.409750275-06:00","closed_at":"2026-07-06T14:39:30.409750275-06:00","close_reason":"Merged in PR #224 to test. TokenManager (login/2FA/refresh/atomic 0600 persistence/server-side logout) + tv_auth CLI + 53 tests at 100% coverage. Live-verified: devonjones (id 47139) login, status, and refresh rotation against the real v2 API. Unblocks gn2 together with hnr (HAR capture).","dependencies":[{"issue_id":"openforge_catalog-7dg","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:42:52.071225891-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-8yb","title":"Propagate thingiverse sync data to AWS prod (fixture + API upsert path)","description":"The tool runs against the LOCAL Postgres, but prod (AWS Lambda + serverless Postgres) is populated by replaying fixture JSON through the Flask API (bin/upload_fixture with OPENFORGE_BASE_URL, same pattern as blueprint fixtures). Thingiverse data (blueprint_id \u003c-\u003e thing_id mapping, public thing URLs) must ride that path so the app can render Thingiverse links in prod and support deeper integration later. Deliverables: fixture format for thingiverse mappings (exported from the local sync tables), an authenticated API upsert endpoint in the Flask app, and upload_fixture support. Note: prod likely only needs the mapping/links, not the per-file hash ledger — that is local operational state; decide the split when designing the fixture.","status":"open","priority":2,"issue_type":"feature","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:55:33.474857151-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T11:55:33.474857151-06:00","dependencies":[{"issue_id":"openforge_catalog-8yb","depends_on_id":"openforge_catalog-750","type":"blocks","created_at":"2026-07-06T11:55:47.512062985-06:00","created_by":"Devon Jones"},{"issue_id":"openforge_catalog-8yb","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:55:47.882392741-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-8yb","title":"Propagate thingiverse sync data to AWS prod (fixture + API upsert path)","description":"The tool runs against the LOCAL Postgres, but prod (AWS Lambda + serverless Postgres) is populated by replaying fixture JSON through the Flask API (bin/upload_fixture with OPENFORGE_BASE_URL, same pattern as blueprint fixtures). Thingiverse data (blueprint_id \u003c-\u003e thing_id mapping, public thing URLs) must ride that path so the app can render Thingiverse links in prod and support deeper integration later. Deliverables: fixture format for thingiverse mappings (exported from the local sync tables), an authenticated API upsert endpoint in the Flask app, and upload_fixture support. Note: prod likely only needs the mapping/links, not the per-file hash ledger — that is local operational state; decide the split when designing the fixture.","notes":"DESIGN NOTE from PR #225 review: the schema allows one blueprint to appear in MULTIPLE things (partial unique index is per-thing only, and test_same_source_allowed_in_different_things pins that behavior). The prod fixture mapping is therefore 1:N — (blueprint_id, thing_id, public_url) derived per thingiverse_files row, not a unique-per-blueprint map. The app's Thingiverse links UI must handle a blueprint linking to several things.","status":"open","priority":2,"issue_type":"feature","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:55:33.474857151-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T14:51:24.318740515-06:00","dependencies":[{"issue_id":"openforge_catalog-8yb","depends_on_id":"openforge_catalog-750","type":"blocks","created_at":"2026-07-06T11:55:47.512062985-06:00","created_by":"Devon Jones"},{"issue_id":"openforge_catalog-8yb","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:55:47.882392741-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-ad5","title":"Sync engine: diff local files vs remote hashes, reconcile","description":"For each managed thing: diff manifest-directed local files against remote files using hash comparison (via thingiverse_file ledger) -\u003e upload new, replace changed, delete removed, patch drifted metadata. Idempotent; dry-run mode showing planned actions before mutating. Depends on hash-algorithm verification: if remote is SHA-256, compute+store SHA-256 alongside catalog MD5s.","notes":"PRIOR ART (old v1 tool): tv_update_description did bulk find/replace of boilerplate across all things matching a name filter, with --dry-run (desc_update.json shows real mass migrations happened). tv_tag_dl mirrored all things to local JSON with 3s sleeps (self-rate-limiting; v1 had practical rate limits). Lessons: (1) metadata drift detection should cover the shared-boilerplate case so a boilerplate change re-syncs every managed thing's description; (2) throttle API calls; (3) dry-run is a first-class requirement, already in scope.","status":"open","priority":1,"issue_type":"feature","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:42:26.401028262-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T12:00:34.191543122-06:00","dependencies":[{"issue_id":"openforge_catalog-ad5","depends_on_id":"openforge_catalog-gn2","type":"blocks","created_at":"2026-07-06T11:42:43.166238543-06:00","created_by":"Devon Jones"},{"issue_id":"openforge_catalog-ad5","depends_on_id":"openforge_catalog-750","type":"blocks","created_at":"2026-07-06T11:42:43.606420026-06:00","created_by":"Devon Jones"},{"issue_id":"openforge_catalog-ad5","depends_on_id":"openforge_catalog-d7a","type":"blocks","created_at":"2026-07-06T11:42:44.00974978-06:00","created_by":"Devon Jones"},{"issue_id":"openforge_catalog-ad5","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:42:53.860069002-06:00","created_by":"Devon Jones"}]}
{"id":"openforge_catalog-bll","title":"Multi-Angle Thumbnail Viewing System","description":"Enable users to view STL models from 10 isometric camera angles with interactive controls. Admins can set default viewing angles per model. System generates 10 isometric-perspective angles (6 primary directions + 4 diagonal corners) during file scan using stl-thumb --cam-pos, combined into single sprite sheet PNG. Frontend has drag-to-rotate and keyboard navigation. All angles maintain 3/4 view for depth, not flat orthographic.","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-21T09:57:50.607001989-07:00","updated_at":"2025-12-21T10:09:20.457266019-07:00"}
{"id":"openforge_catalog-d7a","title":"Manifest schema + metadata assembler","description":"Define per-thing manifest format (YAML): explicit file list for the thing plus field overrides. Assembler builds the thing payload with defaults pulled from catalog Postgres blueprint records (name, description, tag hierarchy -\u003e Thingiverse tags, category, license, images) and applies manifest overrides on top. Zero-manual-entry defaults, curated where it matters. Payload field names/shape finalized against the HAR contract.","notes":"PRIOR ART (old v1 tool): bin/new.*.json templates were per-product-line defaults (openforge2, openlock, construction_kit, miniature, tools): license, category, tags, boilerplate description. Key design lesson: descriptions = per-thing content + SHARED BOILERPLATE FOOTER (Patreon/tutorials/catalog links) that changes over time. Model boilerplate as a shared block composed at assembly time (stored once, referenced by manifests), not baked into each manifest — enables bulk boilerplate updates via re-sync. Old templates: ~/Dropbox/projects/Hardware/objects/OpenForgeDevelopment/openforge/bin/new.*.json","status":"open","priority":2,"issue_type":"feature","owner":"devon.jones@gmail.com","created_at":"2026-07-06T11:42:25.496132115-06:00","created_by":"Devon Jones","updated_at":"2026-07-06T12:00:33.768875881-06:00","dependencies":[{"issue_id":"openforge_catalog-d7a","depends_on_id":"openforge_catalog-4kx","type":"parent-child","created_at":"2026-07-06T11:42:52.892986073-06:00","created_by":"Devon Jones"}]}
Expand Down
2 changes: 1 addition & 1 deletion .beads/last-touched
Original file line number Diff line number Diff line change
@@ -1 +1 @@
openforge_catalog-7dg
openforge_catalog-8yb
Loading