56 lines
3.6 KiB
Markdown
56 lines
3.6 KiB
Markdown
# OpenSpec Change: enterprise-exif
|
|
|
|
- **Change ID**: enterprise-exif
|
|
- **Package**: `@suaveplan/exif`
|
|
- **Category**: universal
|
|
- **Target path**: `universal/media/exif`
|
|
- **Status**: PROPOSED
|
|
- **Date**: 2026-04-19
|
|
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/exif.md`
|
|
|
|
## Summary
|
|
Greenfield rebuild of `@suaveplan/exif` — a comprehensive, dependency-free, runtime-agnostic metadata reader/writer/stripper for JPEG, PNG, WebP, TIFF, HEIC/ISOBMFF, and RAW images. Supports EXIF, XMP, IPTC, ICC, GPS, and MakerNotes (Apple, Canon, Nikon, Sony, incl. ciphered MakerNote decoders). The package's main-branch change `openspec/changes/exif-migration` is the most recent authoritative delta and is folded in here.
|
|
|
|
## Current-state audit (genesis)
|
|
Package does not exist yet — fresh build. Main branch has `universal/exif` with 40+ exported primitives.
|
|
|
|
## Dependencies
|
|
- Workspace: none (leaf)
|
|
- External (via catalog): `zod`, `tslib`, `@opentelemetry/api`
|
|
- Dev (via catalog): `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata`
|
|
|
|
## Preserved public surface (grouped)
|
|
|
|
### Binary primitives
|
|
`ByteReader`, `ByteWriter`, `ByteOrder`, `crc32`, `crc32Multi`, `md5`, `md5Hex`, `numberToRational`, `rationalToNumber`, `Rational`.
|
|
|
|
### Core dispatch
|
|
`detectImageFormat`, `readMetadata`, `writeMetadata`, `stripMetadata`, `ReadOptions`, `StripOptions`.
|
|
|
|
### Format-specific
|
|
JPEG: `readJpegSegments`, `writeJpegSegments`. PNG: `readPng`, `writePng`. TIFF: `readTiffMetadata`, `writeTiffMetadata`. WebP: `readWebp`, `writeWebp`. ISOBMFF/HEIC: `findAllBoxes`, `findBox`, `readBoxes`, `readFtypBrands`, `readIsobmffMetadata`, `writeIsobmffMetadata`. RAW: `detectRaw`.
|
|
|
|
### IFD engine
|
|
`parseTiff`, `ParsedTiff`, `ParseOptions`, `buildTiff`, `BuildInput`, `IfdEntry`, `TiffType`, `decodeEntryValue`, `encodeEntryValue`, `entrySize`, `TIFF_TYPE`, `TIFF_TYPE_SIZE`.
|
|
|
|
### GPS, IPTC, XMP, ICC
|
|
GPS: `decimalToDms`, `dmsToDecimal`, `formatDms`, `gpsToIsoTimestamp`, `isoToGpsFields`, `LatRef`, `LonRef`. IPTC: `readIptc`, `writeIptc`. XMP: `readXmp`, `writeXmp`, `XMP_NAMESPACES`, `namespaceFor`. ICC: `readIccProfile`, `writeIccProfile`, `validateIccProfile`, `classifyProfile`, `isSRGB`, `isAdobeRGB`, `isDisplayP3`, `profileDescription`.
|
|
|
|
### MakerNotes
|
|
`decodeMakerNote`, `decodeAppleMakerNote`, `decodeBplist`, `decodeCanonMakerNote`, `decodeNikonMakerNote`, `nikonDecrypt`, `nikonEncrypt`, `sonyDecrypt`, `sonyEncrypt`.
|
|
|
|
### Types
|
|
`ExifData`, `ExifIfd`, `ExifValue`, `IccCurve`, `IccDateTime`, `IccHeader`, `IccProfile`, `IccTagValue`, `IccText`, `IccXyz`, `ImageFormat`, `ISOBMFF_FAMILY`, `TIFF_FAMILY`, `ImageMetadata`, `CameraInfo`, `ExposureInfo`, `GpsCoordinates`, `LensInfo`, `IptcData`, `IptcValue`, `MakerNote`, `MakerNoteVendor`, `GpsPatch`, `MakerNotePatch`, `MetadataPatch`, `XmpData`, `XmpScalar`, `XmpStruct`, `XmpValue`.
|
|
|
|
## New genesis additions
|
|
- Codes: `EXIF.UNSUPPORTED_FORMAT`, `EXIF.PARSE_ERROR`, `EXIF.WRITE_FAILED`, `EXIF.INVALID_IFD`, `EXIF.BUFFER_OVERRUN`.
|
|
- Zod schemas for every wire-facing type: `ExifDataSchema`, `ImageMetadataSchema`, `MetadataPatchSchema`.
|
|
- OTel histograms per format: `exif.read.duration_ms{format}`, `exif.write.duration_ms{format}`, `exif.strip.duration_ms{format}`.
|
|
- Property tests: strip is idempotent; read→write→read yields equal metadata; GPS DMS↔decimal round-trip; `numberToRational`→`rationalToNumber` within tolerance.
|
|
- Differential fuzzing harness against `exifr` for read parity on corpus of 1 000 real images.
|
|
|
|
## Impact
|
|
- Adds one new package: `universal/media/exif`
|
|
- Adds one new spec capability: `exif`
|
|
- Unblocks `metadata`, `image`, `react-image` (downstream waves).
|