Photography joins the platform as a dedicated interest area so newcomers skip the desktop toolchain (Adobe Camera Raw → Photoshop jsx batch → Zerene Stacker → manual touch-up). Built from Joey's real workflow: OM SYSTEM OM-1 Mark II, .ORF raw, focus stacks.
Verified foundation (Joey's actual files, exiftool)
OM-1 Mark II ORFs carry 266 tags/frame: full gear identity (body + lens serials — 2 lenses already distinguishable), the student exposure septet (OM 90mm F3.5 · f/8 · 1/200 · ISO 200 · no flash), focus-stack metadata (FocusDistance 0.535 m, FocusStepCount — the fusion depth prior), DateTimeOriginal + real timezone offset, GPS when the phone link was on (verified), and an embedded ~1MB JPEG preview + thumbnail → instant gallery derivatives with zero raw processing
Joey's stack_pipeline/ Python package (stack detection, Tenengrad curation, OpenCV pyramid + FocusStepCount-guided depth-map fusion, WB sync) is the fusion core to productionize
His ORF_to_TIFF.jsx ACR recipe (Enhance Raw Details, Sharpening 10, remove CA) becomes the Darkroom Companion payload
Decisions
Develop engines: rawpy/LibRaw server-side default + automated Adobe leg via a desktop companion agent on Joey's Mac (Adobe has no server CLI; own-desktop scripting is supported)
Private gallery; per-photo location opt-in; parental Photography + PhotoLocationSharing permissions for minors; blog-linking exposes only the linked photo in context
ORF originals kept forever (photos bucket); per-frame upload (no giant multipart — existing 100MB/10MB/12-file caps all break at 10–60 × 17MB)
Architecture + reuse map (blog-pipeline fork for upload, ArtStudio job machinery for stacking, VaultItem triad for the personal library, country-map for pins) is in the approved plan; PR bodies will carry the per-slice detail.
## Vision
Photography joins the platform as a dedicated interest area so newcomers skip the desktop toolchain (Adobe Camera Raw → Photoshop jsx batch → Zerene Stacker → manual touch-up). Built from Joey's real workflow: OM SYSTEM OM-1 Mark II, .ORF raw, focus stacks.
## Verified foundation (Joey's actual files, exiftool)
- OM-1 Mark II ORFs carry **266 tags/frame**: full gear identity (body + lens serials — 2 lenses already distinguishable), the student exposure septet (`OM 90mm F3.5 · f/8 · 1/200 · ISO 200 · no flash`), **focus-stack metadata** (FocusDistance 0.535 m, FocusStepCount — the fusion depth prior), DateTimeOriginal + real timezone offset, **GPS when the phone link was on** (verified), and an **embedded ~1MB JPEG preview + thumbnail → instant gallery derivatives with zero raw processing**
- Joey's `stack_pipeline/` Python package (stack detection, Tenengrad curation, OpenCV pyramid + FocusStepCount-guided depth-map fusion, WB sync) is the fusion core to productionize
- His `ORF_to_TIFF.jsx` ACR recipe (Enhance Raw Details, Sharpening 10, remove CA) becomes the Darkroom Companion payload
## Decisions
- Develop engines: **rawpy/LibRaw server-side default + automated Adobe leg** via a desktop companion agent on Joey's Mac (Adobe has no server CLI; own-desktop scripting is supported)
- **Private gallery**; per-photo location opt-in; parental `Photography` + `PhotoLocationSharing` permissions for minors; blog-linking exposes only the linked photo in context
- **ORF originals kept forever** (`photos` bucket); per-frame upload (no giant multipart — existing 100MB/10MB/12-file caps all break at 10–60 × 17MB)
- One epic burn, 9 PR trains
## PR trains
1. Backend: Photograph domain + upload + `FeaturePermissions` additions + gear registry
2. Backend: PhotographProcessor worker (scan → exiftool metadata + embedded-preview extraction → move, **no EXIF strip**) + infra + `photos` bucket provisioning
3. Angular: domain-photograph lib + photo-gallery tool (thumbnail + medium views) + parent toggles
4. Angular: lightbox (large + large-with-student-meta, ←/→) + location opt-in + photo map + profile tab
5. Backend+artpipe: PhotoStack asset type (develop → align_fuse → finalize), multi-input seam, `photostack` CPU ModelBackend (vendored stack_pipeline + rawpy), baked image, worker deploy
6. Angular: Photo Stack view (5th Art Studio tab) — frame picker, engine/method config, SignalR progress
7. Darkroom Companion CLI + develop-job endpoints (Adobe-quality develop leg, rawpy fallback)
8. Angular: touch-up canvas editor (paint source frames onto composite, Zerene-style)
9. Blog/comment photo-linking + e2e + es i18n
Architecture + reuse map (blog-pipeline fork for upload, ArtStudio job machinery for stacking, VaultItem triad for the personal library, country-map for pins) is in the approved plan; PR bodies will carry the per-slice detail.
Monitoring note (2026-07-19 ~17:00Z): both new SERVER-pinned services from this epic were reject-looping since deploy (~07:19Z / 07:59Z) — invalid mount config ... bind source path does not exist for /mnt/fusionio/spikersoft/photographs and /mnt/fusionio/spikersoft/uploads/photographs. Neither PR-2 nor PR-5 provisions the host dirs and no runbook step covers it. Created both dirs (mode 0777, matching every sibling tree) via a one-shot job on SERVER; spikersoft-photograph-processor and artpipe-photostack now 1/1, consumers listening, photos-svc S3 key interpolated correctly (40 chars). Suggest adding a mkdir provisioning line to the stack headers/runbook so a rebuild of SERVER doesn't regress this.
Monitoring note (2026-07-19 ~17:00Z): both new SERVER-pinned services from this epic were reject-looping since deploy (~07:19Z / 07:59Z) — `invalid mount config ... bind source path does not exist` for `/mnt/fusionio/spikersoft/photographs` and `/mnt/fusionio/spikersoft/uploads/photographs`. Neither PR-2 nor PR-5 provisions the host dirs and no runbook step covers it. Created both dirs (mode 0777, matching every sibling tree) via a one-shot job on SERVER; spikersoft-photograph-processor and artpipe-photostack now 1/1, consumers listening, photos-svc S3 key interpolated correctly (40 chars). Suggest adding a mkdir provisioning line to the stack headers/runbook so a rebuild of SERVER doesn't regress this.
Epic complete — every one of the 9 PR trains shipped, plus substantial post-scope hardening. Closing.
Train map (all merged + deployed):
1-2. Photograph domain/upload/permissions/gear + PhotographProcessor worker (scan → exiftool → previews → move, no EXIF strip)
3-4. domain-photograph lib, photo-gallery tool, lightbox + student meta, location opt-in, photo map, profile tab
5-6. PhotoStack ArtAsset pipeline (develop → align_fuse) + the Art Studio Photo Stack tab w/ SignalR progress
7. Darkroom Companion CLI (tools/darkroom-companion) + develop-job endpoints
8. Touch-up canvas editor — since enhanced with the compare divider + selected-frame prominence (#780)
9. Blog photo-linking (+ sanitized photograph-info), authenticated e2e coverage, es i18n
Post-scope work that grew out of the epic (all landed): stack-aware gallery — EXIF burst auto-grouping, collapse-to-finished-products, server-side provenance snapshots + "How this was made" transparency panel, owner deletion with stack-frame restore (#779); Stacked/Touchup metadata inheritance closing the canvas-EXIF gap (#755); photograph previews + art-asset artifacts migrated off GridFS to MinIO (#778/#783, #783 PRs pending merge — tracked separately).
Epic complete — every one of the 9 PR trains shipped, plus substantial post-scope hardening. Closing.
Train map (all merged + deployed):
1-2. Photograph domain/upload/permissions/gear + PhotographProcessor worker (scan → exiftool → previews → move, no EXIF strip)
3-4. domain-photograph lib, photo-gallery tool, lightbox + student meta, location opt-in, photo map, profile tab
5-6. PhotoStack ArtAsset pipeline (develop → align_fuse) + the Art Studio Photo Stack tab w/ SignalR progress
7. Darkroom Companion CLI (tools/darkroom-companion) + develop-job endpoints
8. Touch-up canvas editor — since enhanced with the compare divider + selected-frame prominence (#780)
9. Blog photo-linking (+ sanitized photograph-info), authenticated e2e coverage, es i18n
Post-scope work that grew out of the epic (all landed): stack-aware gallery — EXIF burst auto-grouping, collapse-to-finished-products, server-side provenance snapshots + "How this was made" transparency panel, owner deletion with stack-frame restore (#779); Stacked/Touchup metadata inheritance closing the canvas-EXIF gap (#755); photograph previews + art-asset artifacts migrated off GridFS to MinIO (#778/#783, #783 PRs pending merge — tracked separately).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Vision
Photography joins the platform as a dedicated interest area so newcomers skip the desktop toolchain (Adobe Camera Raw → Photoshop jsx batch → Zerene Stacker → manual touch-up). Built from Joey's real workflow: OM SYSTEM OM-1 Mark II, .ORF raw, focus stacks.
Verified foundation (Joey's actual files, exiftool)
OM 90mm F3.5 · f/8 · 1/200 · ISO 200 · no flash), focus-stack metadata (FocusDistance 0.535 m, FocusStepCount — the fusion depth prior), DateTimeOriginal + real timezone offset, GPS when the phone link was on (verified), and an embedded ~1MB JPEG preview + thumbnail → instant gallery derivatives with zero raw processingstack_pipeline/Python package (stack detection, Tenengrad curation, OpenCV pyramid + FocusStepCount-guided depth-map fusion, WB sync) is the fusion core to productionizeORF_to_TIFF.jsxACR recipe (Enhance Raw Details, Sharpening 10, remove CA) becomes the Darkroom Companion payloadDecisions
Photography+PhotoLocationSharingpermissions for minors; blog-linking exposes only the linked photo in contextphotosbucket); per-frame upload (no giant multipart — existing 100MB/10MB/12-file caps all break at 10–60 × 17MB)PR trains
FeaturePermissionsadditions + gear registryphotosbucket provisioningphotostackCPU ModelBackend (vendored stack_pipeline + rawpy), baked image, worker deployArchitecture + reuse map (blog-pipeline fork for upload, ArtStudio job machinery for stacking, VaultItem triad for the personal library, country-map for pins) is in the approved plan; PR bodies will carry the per-slice detail.
Monitoring note (2026-07-19 ~17:00Z): both new SERVER-pinned services from this epic were reject-looping since deploy (~07:19Z / 07:59Z) —
invalid mount config ... bind source path does not existfor/mnt/fusionio/spikersoft/photographsand/mnt/fusionio/spikersoft/uploads/photographs. Neither PR-2 nor PR-5 provisions the host dirs and no runbook step covers it. Created both dirs (mode 0777, matching every sibling tree) via a one-shot job on SERVER; spikersoft-photograph-processor and artpipe-photostack now 1/1, consumers listening, photos-svc S3 key interpolated correctly (40 chars). Suggest adding a mkdir provisioning line to the stack headers/runbook so a rebuild of SERVER doesn't regress this.Epic complete — every one of the 9 PR trains shipped, plus substantial post-scope hardening. Closing.
Train map (all merged + deployed):
1-2. Photograph domain/upload/permissions/gear + PhotographProcessor worker (scan → exiftool → previews → move, no EXIF strip)
3-4. domain-photograph lib, photo-gallery tool, lightbox + student meta, location opt-in, photo map, profile tab
5-6. PhotoStack ArtAsset pipeline (develop → align_fuse) + the Art Studio Photo Stack tab w/ SignalR progress
7. Darkroom Companion CLI (tools/darkroom-companion) + develop-job endpoints
8. Touch-up canvas editor — since enhanced with the compare divider + selected-frame prominence (#780)
9. Blog photo-linking (+ sanitized photograph-info), authenticated e2e coverage, es i18n
Post-scope work that grew out of the epic (all landed): stack-aware gallery — EXIF burst auto-grouping, collapse-to-finished-products, server-side provenance snapshots + "How this was made" transparency panel, owner deletion with stack-frame restore (#779); Stacked/Touchup metadata inheritance closing the canvas-EXIF gap (#755); photograph previews + art-asset artifacts migrated off GridFS to MinIO (#778/#783, #783 PRs pending merge — tracked separately).