Adds docs/nip71-migration-plan.md — the agreed spec to build from:
- Dual-event, opt-in (off by default): keep canonical kind 30078; add addressable
34235/34236 mirror (d=videoRootId, edits in lockstep).
- Research correction: 34235/36 are NOT deprecated — current NIP-71 designates the
addressable pair for content that needs post-publication updates (exactly bitvid's
edit-in-place model).
- WebTorrent rides STANDARD NIP-94 imeta fields (magnet, i) rather than a hack;
private videos never mirrored; HTTPS url required to mirror.
- Phases: 0 retarget builders → 1 outbound publish/edit/delete → 1.5 NIP-89 "Open in
bitvid" handler + NIP-51 kind 30005 portable playlists → 2 inbound ingest.
Also refreshes docs/nips/71.md (was stale: only 21/22; now the current 233-line
spec with 34235/36 addressable kinds, waveform, origin, multi-audio). Updates
TODO #17 to point at the plan.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Two new content-type backlog items (research-first): watch-only Nostr live
streams from zap.stream/shosho.live (likely NIP-53 kind 30311 + 1311 chat), and
consuming external short-form/NIP-71 video notes (likely kind 22/21) from apps
like Amethyst. Flags that these are two distinct NIPs, not the same thing.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Captures the requested feature: optionally sync S3/R2 storage credentials and the
NWC zap wallet URI across logins via a self-encrypted NIP-78 (kind 30078) note,
unlocked by the signer. Includes the design path (reuse the existing envelope
encryption for storage creds; NIP-44-to-self for the NWC URI), the relay/
replaceable lessons from this session (write relays, strictly-newer created_at,
newest-per-d-tag on read, empty-publish to clear), opt-in UX, and the threat
model (public-relay blob, key-compromise trust root, NWC = spending capability,
signer decrypt budget).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Adds this session's deferred/discovered work: My Videos Restore action, info.json
upload sidecar (with privacy guard), orphan size/date metadata, confirm-modal
polish, external-URL liveness caveat; plus the on-demand deploy workflow decision
(beta?) and the env-sensitive visual-regression baseline that needs CI-side
regeneration. Marks the orphan-GC item as largely delivered by the My Videos tab,
and logs the completed My Videos / delete / watch-history / CI / Vercel work.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
connectRemoteSigner and useStoredRemoteSigner accepted but never used the
`validator` the auth provider passes (accessControl.canAccess) -- so NIP-46
logins bypassed the block/allow gate that nsec/NIP-07 logins enforce. (The
validation lived only on the unused Nip46Connector.)
Both paths now run the validator against the remote signer's resolved user
pubkey BEFORE activating the signer (via _enforceRemoteSignerValidator): the
validator throws on a blocked/non-permitted pubkey, or returning false rejects
with code remote-signer-access-denied. A stored session rejected by the
validator is forgotten so a blocked pubkey can't keep retrying.
Residual (noted in TODO): the silent startup auto-restore
(scheduleStoredRemoteSignerRestore) still reconnects without a validator.
Test: tests/nostr/nip46-prepare-handshake.test.mjs (validator throws / false /
true / absent). Full suite green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Two gaps where generic S3 trailed Cloudflare R2:
1. Object cleanup on delete/edit didn't work for generic S3. deleteVideoStorage
built its client via makeR2Client, which hard-forces path-style and ignores
the connection's forcePathStyle -- so vhost-style S3 deletes were misaddressed
and cleanup silently failed (S3 users' deleted/edited files orphaned). It is
now provider-aware (mirrors uploadFile): R2 -> makeR2Client (path-style),
generic S3 -> makeS3Client honoring forcePathStyle. makeS3Client is now
injectable for testing.
2. CORS guidance on upload failure was R2-only. Extracted isLikelyCorsError +
a generic-S3 guidance builder into js/utils/uploadErrorHints.js (re-exported
from r2Service for back-compat); s3UploadService now appends actionable CORS
guidance on an opaque "Failed to fetch" too.
Generic S3 is now at functional parity with R2 for upload -> publish -> cleanup.
Tests: r2-delete-video-storage (adds generic-S3 forcePathStyle routing),
s3-upload-cors-guidance (new). Full suite green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A new user's top first-upload failure is a missing R2 CORS policy (browser
PUT/POST blocked) -- and object-scoped R2 tokens often cannot auto-set CORS.
The connection test already surfaces buildCorsGuidance on the opaque
"Failed to fetch", but a user who skips the test and uploads directly got a
bare "Upload failed: Failed to fetch". The upload error handler now detects the
browser CORS/network rejection (isLikelyCorsError -- Chrome "Failed to fetch",
Firefox "NetworkError", Safari "Load failed") and appends the same actionable
guidance. Updated the R2 follow-up TODO (credential audit done; CORS reviewed).
Test: tests/services/r2-cors-error-classifier.test.mjs. Full suite green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Captures remaining R2 work after the upload audit + object-cleanup increments:
credential-security review, bucket/custom-domain provisioning audit, CDN purge
integration, and follow-ups to the cleanup work (generic-S3 cleanup, all-versions
delete cleanup, edit thumbnail cleanup). Plus the Vercel production-branch parking
lot item.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Executed unit tests (passed).
- Detected flakiness in subsequent test runs (timeout).
- Performed static analysis (zero assertions, timing, console usage).
- Generated test audit report and saved to `artifacts/`.
- Updated test logs and flakiness matrix.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Executed test-audit-agent daily task.
- Generated audit report in docs/agents/task-logs/daily/.
- Added reusable scripts in test-audit/ for flakiness check and static analysis.
- Verified test suite (shard 1) and identified failure in hashtag-preferences.test.mjs.
Co-authored-by: PR0M3TH3AN <[email protected]>