- Fix BlossomView blob list not refreshing after upload by replacing
getDisplayBlobs() function call with reactive $: displayBlobs declaration
- Fix EventsView not reflecting login state by moving permission check
from EventsView template to App.svelte where reactive variables live
- Await fetchUserRole() in loadRelayData() to prevent race condition
during auto-login from localStorage
- Trigger explicit event loading after handleLogin() completes
- Center login prompts and permission messages in main content panel
using margin:auto and align-items:center on main-content flex container
- Add warning log for blossom upload auth validation failures
- Remove temporary debug logging from blossom handlers
- Bump version to v0.58.7
Files modified:
- app/web/src/App.svelte: Permission gating, event loading, centered prompts
- app/web/src/BlossomView.svelte: Reactive displayBlobs declaration
- app/web/src/EventsView.svelte: Remove internal permission checks
- pkg/blossom/handlers.go: Clean up debug logging, add auth failure warning
- pkg/version/version: v0.58.7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document pluggable Transport interface and how to add transports
- Add relay.orly.dev deployment section (correct: x86_64, not ARM64)
- Document SSH access, build, deploy, and blue-green strategy notes
- Update architecture tree with transport packages
- Add transport/ to interface design list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Define Transport interface (Name, Start, Stop, Addresses) at pkg/interfaces/transport/
- Add Transport Manager with ordered startup/shutdown at pkg/transport/
- Create TCP transport (pkg/transport/tcp/) wrapping plain http.Server
- Create TLS transport (pkg/transport/tls/) with ACME + manual certs
- Create Tor transport (pkg/transport/tor/) wrapping existing pkg/tor service
- Replace ~220 lines of inline transport code in app/main.go with manager
- Simplify shutdown handler to single transportMgr.StopAll() call
- Use transportMgr.Addresses() for NIP-11 relay info (replaces torService)
Files modified:
- pkg/interfaces/transport/transport.go: New transport interface
- pkg/transport/manager.go: New transport manager
- pkg/transport/tcp/tcp.go: New TCP transport
- pkg/transport/tls/tls.go: New TLS/ACME transport (moved from app/tls.go)
- pkg/transport/tor/tor.go: New Tor transport wrapper
- app/main.go: Use transport manager for all networking
- app/server.go: Replace torService field with transportMgr
- app/handle-relayinfo.go: Use transportMgr.Addresses()
- app/tls.go: Deleted (moved to pkg/transport/tls/)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace manual GetSerialsByRange + FetchEventBySerial loops in
Configure() and adminRelays() with single batched QueryEvents calls
- Reduces N*(1+M) gRPC round-trips to 1 call per query, cutting ACL
startup from >2 minutes to sub-second
- Handle Configure errors gracefully instead of os.Exit(1) to support
empty databases (syncer populates follows from external relays)
- Remove unused database/indexes/types import
Files modified:
- pkg/acl/follows.go: Batched QueryEvents for kind 3 and kind 10002
- cmd/orly-acl-follows/main.go: Graceful error handling on configure
- pkg/version/version: Bump to v0.58.6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update nostr dependency to use local replace for v1.0.18 fixes:
channels→slices, frame size enforcement, responder ID list splitting
- Fix protoToFilter() to convert Ids, Kinds, Authors, Since, Until fields
from proto filter (was only converting Limit)
- Refactor manager sync flow into phases (reconcile → fetch → push)
- Expand negentropy test infrastructure with orly relay support
Files modified:
- go.mod, go.sum: Add replace directive for nostr v1.0.18
- pkg/sync/negentropy/embedded.go: Fix protoToFilter conversion
- pkg/sync/negentropy/manager.go: Refactor sync phases
- tests/negentropy/: Expand test infrastructure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add localOnly checkbox to ComposeView, defaulting to checked
- When checked, event is published only to the local ORLY relay
- When unchecked, event is also broadcast to configured relays
via nostrClient.publish() (SimplePool)
- Bump version to v0.58.4
Files modified:
- app/web/src/ComposeView.svelte: Add localOnly prop, checkbox UI, styles
- app/web/src/App.svelte: Wire composeLocalOnly state, conditional broadcast
- app/web/dist/: Rebuilt bundle
- pkg/version/version: v0.58.3 -> v0.58.4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bump git.mleku.dev/mleku/nostr from v1.0.16 to v1.0.17
- Remove replace directive pointing to local path
- v1.0.17 includes negentropy protocol fixes for C++ interop
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add recover() and capacity check to prevent crash when event ID slice
has corrupted header (nil data pointer with non-zero length).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix createNIP98AuthHeader and createNIP98Auth in App.svelte to use
userSigner.signEvent() for all auth methods instead of generating
mock signatures for nsec logins
- Add direct GET-based download for open relays (ACL "none") to avoid
browser issues with fetch/blob programmatic downloads
- Add export status feedback (disabled buttons, "Exporting..." text)
- Add cmd/orly-export CLI tool for NIP-98 authenticated relay exports
with progress tracking
- Add vendor/ to .gitignore
- Bump version to v0.58.2
Files modified:
- app/web/src/App.svelte: Fix NIP-98 signing, rewrite export flow
- app/web/src/ExportView.svelte: Add isExporting prop and button states
- app/web/dist/: Rebuilt bundle
- cmd/orly-export/main.go: New CLI export tool
- .gitignore: Add vendor/ exclusion
- pkg/version/version: v0.58.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NIP-77 Protocol Fixes:
- Fix role reversal in HandleNegOpen: relay now correctly requires initial
message from client and calls Reconcile() instead of Start()
- Fix premature event transmission: haveIDs events now only sent when
reconciliation completes (complete=true)
- Add proper error handling for missing initial message in NEG-OPEN
Sync Client Mode (gRPC IPC):
- Add --server flag to 'orly sync' for connecting to running service
- Enable one-shot sync without direct database access
- Support remote sync operations via gRPC
- Add filterToProto helper for gRPC communication
Documentation:
- Add NIP77_ANALYSIS_AND_FIX.md with detailed protocol analysis
- Add SYNC_CLIENT_MODE.md with usage examples and architecture diagrams
Bug Fix:
- Fix nil pointer panic in handle-req.go when subscriptions map is uninitialized
The nostr library now uses its embedded btcec fork for the fallback
signer instead of the separate p256k1.mleku.dev package.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Legacy events stored before compact format (v6 migration) may have IDs
that start with byte 0x01. The v6 migration incorrectly skipped these
events because it checked `eventData[0] == CompactFormatVersion` before
attempting to decode, causing them to never receive SerialEventId (sei)
mappings.
This fix:
1. Changes compact format detection to try sei lookup first - if the
mapping doesn't exist, fall back to legacy binary format instead
of returning an error
2. Adds v9 migration (BackfillMissingSerialEventIdMappings) that finds
legacy events with IDs starting with 0x01 that were skipped by the
v6 migration and creates their sei mappings
3. Quiets the "Key not found" logging for sei lookups since missing
mappings are now expected and handled gracefully
Files modified:
- pkg/database/fetch-events-by-serials.go: Fallback to legacy format
- pkg/database/fetch-event-by-serial.go: Fallback to legacy format
- pkg/database/export.go: Fallback to legacy format
- pkg/database/serial_cache.go: Quiet sei lookup logging
- pkg/database/migrations.go: Add v9 sei backfill migration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add naddr_unique constraint and event_naddr index to schema.go
- Add buildNaddr() helper to compute pubkey:kind:dtag coordinate
- Store naddr on Event nodes for kinds 30000-39999, NULL for others
- Add v5 migration to populate naddr for existing addressable events
Implements: https://git.nostrdev.com/mleku/next.orly.dev/issues/27
Files modified:
- pkg/neo4j/schema.go: Added naddr constraint/index and DROP statements
- pkg/neo4j/save-event.go: Added buildNaddr() and naddr in Event CREATE
- pkg/neo4j/migrations.go: Added v5 migration migrateAddNaddr()
- pkg/version/version: Bumped to v0.58.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update relay help text to clearly explain monolithic mode with embedded
database, ACL, and NIP-77 negentropy all in single binary
- Update release script to focus on monolithic binary as primary deployment
- Clarify that split-mode (gRPC) is optional, not the default
Files modified:
- cmd/orly/relay/relay.go: Expanded help text for monolithic mode
- .claude/commands/release.md: Updated deploy steps for monolithic binary
- pkg/version/version: Bump to v0.57.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create negentropy.Handler interface in pkg/interfaces/negentropy
- Add EmbeddedHandler that wraps negentropy.Manager for embedded mode
- Update app/handle-negentropy.go to use interface instead of gRPC client
- Update gRPC client to implement the Handler interface
- Update startup.go to initialize embedded negentropy when not in gRPC mode
- Enables NIP-77 set reconciliation in monolithic binary without gRPC
Files modified:
- pkg/interfaces/negentropy/negentropy.go: New interface definition
- pkg/sync/negentropy/embedded.go: New embedded handler implementation
- pkg/sync/negentropy/grpc/client.go: Implement Handler interface
- app/handle-negentropy.go: Use interface type
- pkg/relay/startup.go: Initialize embedded negentropy
- pkg/version/version: Bump to v0.57.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add start/stop/restart buttons for individual services in launcher UI
- Show all available modules with categories (Database, ACL, Sync, Certs)
- Add enable/disable toggles with mutual exclusivity for DB/ACL backends
- Handle service dependencies when stopping (DB stops dependents first)
- Advertise NIP-86 in NIP-11 when ACL mode is managed or curating
- Add module descriptions showing API coverage
Files modified:
- app/handle-relayinfo.go: Add NIP-86 to supported NIPs for managed/curating modes
- cmd/orly-launcher/server.go: Add start-service/stop-service endpoints, ProcessStatus fields
- cmd/orly-launcher/supervisor.go: Add StartService, StopService with dependency handling
- cmd/orly-launcher/web/src/api.js: Add startService, stopService API functions
- cmd/orly-launcher/web/src/components/ProcessCard.svelte: Add toggles, categories, action buttons
- cmd/orly-launcher/web/src/pages/Dashboard.svelte: Add service control handlers
- pkg/version/version: Bump to v0.56.9
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify HandleEvent to thin protocol adapter (~320 -> ~130 lines)
- Create ingestion service for full event pipeline orchestration
- Add specialkinds.go for special kind handler registration
- Eliminate global ACL singleton with injectable Registry interface
- Add ACLRegistry() accessor to Server for dependency injection
- Decompose Rule value object into AccessControl, Constraints,
TagValidationConfig sub-components for cleaner organization
- Add LoggingSubscriber for domain event analytics
- Update all policy tests for embedded struct initialization
- Update DDD_ANALYSIS.md to 10/10 maturity score
Files modified:
- app/handle-event.go: Simplified to delegate to ingestion service
- app/specialkinds.go: NEW - Special kind handler registration
- app/server.go: Add aclRegistry field and ACLRegistry() accessor
- pkg/interfaces/acl/acl.go: Add Registry interface
- pkg/acl/acl.go: Add accessor methods for privatized fields
- pkg/policy/policy.go: Decompose Rule into sub-value objects
- pkg/policy/*_test.go: Update struct literals for embedded types
- pkg/event/ingestion/service.go: Add ACLMode, special kinds support
- pkg/event/processing/processing.go: Add domain event dispatcher
- pkg/domain/events/subscribers/logging.go: NEW - Analytics subscriber
- DDD_ANALYSIS.md: Update to 10/10 maturity score
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change IdPkTs Id/Pub fields from []byte to [32]byte (ntypes.EventID/Pubkey)
- Add NewIdPkTs() constructor for copying byte slices into fixed arrays
- Add IDSlice() and PubSlice() methods for slice access when needed
- Update protobuf converters to handle array-to-slice conversion
- Update all database and neo4j creation sites to use NewIdPkTs()
- Fix test files to use bytes.Equal() for array comparisons
- Benchmark confirms 0 B/op, 0 allocs/op for copy operations
Files modified:
- pkg/interfaces/store/store_interface.go: Core type change to fixed arrays
- pkg/interfaces/store/store_interface_test.go: Tests for new API
- pkg/proto/orlydb/v1/converters.go: Protobuf conversion with ntypes
- pkg/database/get-fullidpubkey-by-serial.go: Use NewIdPkTs constructor
- pkg/database/get-fullidpubkey-by-serials.go: Use NewIdPkTs constructor
- pkg/database/process-delete.go: Slice arrays for DeleteEvent calls
- pkg/neo4j/fetch-event.go: Use NewIdPkTs constructor
- pkg/neo4j/query-events.go: Use NewIdPkTs constructor
- pkg/database/query-for-*_test.go: Use bytes.Equal for comparisons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Include pre-built libraries in lib/secp256k1/ directory
- Update CI workflow to use local libraries instead of nostr module
- Update release notes to indicate ARM64 libsecp256k1 included
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Building from source was failing. The nostr module already has
a properly built libsecp256k1.so with schnorr/musig2 support.
ARM64 users need to build libsecp256k1 from source separately.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cross-compile with schnorr/musig2 support for both architectures.
System packages lack these Nostr-required features.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
System packages lack schnorr/musig2 support needed for Nostr.
Copy the custom-built library from git.mleku.dev/mleku/nostr/crypto/p8k/.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The library was removed from the repo - it's loaded at runtime via purego.
Users must install libsecp256k1 separately (apt install libsecp256k1-1).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ServicesEnabled config to run admin UI without starting services
- Add start/stop services API endpoints and dashboard controls
- Add IsRunning() method to supervisor for service state tracking
- Fix release download URLs to use git.nostrdev.com instead of git.mleku.dev
- Change Makefile to use go install (except main relay uses go build for name)
- Add orly-certs DNS-01 wildcard certificate manager
- Remove libsecp256k1.so from repo (runtime dependency only)
Files modified:
- cmd/orly-launcher/config.go: Add ServicesEnabled option
- cmd/orly-launcher/main.go: Skip services when disabled, update help
- cmd/orly-launcher/server.go: Add start/stop endpoints, fix tags API URL
- cmd/orly-launcher/supervisor.go: Add IsRunning(), allow restart after stop
- cmd/orly-launcher/web/src/api.js: Add startServices/stopServices functions
- cmd/orly-launcher/web/src/pages/Dashboard.svelte: Add start/stop buttons
- cmd/orly-launcher/web/src/pages/Update.svelte: Fix release base URL
- cmd/orly-certs/: New DNS-01 certificate manager
- Makefile: Use go install, keep go build for main relay
- pkg/version/version: Bump to v0.56.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add jq installation step for JSON processing
- Delete existing release before creating new one (handles re-runs)
- Fetch tag to ensure it exists before release creation
- Use jq properly for JSON payload construction
- Fix release body indentation
Files modified:
- .gitea/workflows/go.yml: Improved release workflow
- pkg/version/version: Bump to v0.56.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add embedded Svelte admin web UI for process monitoring and control
- Implement NIP-98 HTTP authentication middleware for secure API access
- Add binary update/rollback system with versioned symlinks
- Add admin API endpoints: status, config, binaries, update, restart, rollback
- Update CI workflow to build all binaries for AMD64 and ARM64 architectures
- Add launcher-web Makefile target for building admin UI separately
Files modified:
- .gitea/workflows/go.yml: Build all binaries and launcher admin UI
- Makefile: Add launcher-web and orly-launcher-no-web targets
- cmd/orly-launcher/auth.go: NIP-98 authentication middleware
- cmd/orly-launcher/config.go: Admin UI configuration (port, owners)
- cmd/orly-launcher/main.go: Start admin server, updated help text
- cmd/orly-launcher/server.go: Admin HTTP server with API endpoints
- cmd/orly-launcher/supervisor.go: GetProcessStatuses, RestartAll methods
- cmd/orly-launcher/updater.go: Binary version management with symlinks
- cmd/orly-launcher/web.go: Embedded admin UI serving
- cmd/orly-launcher/web/: Svelte admin UI (dashboard, config, update pages)
- pkg/version/version: Bump to v0.55.11
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add O(1) direct lookup for parameterized replaceable events (kinds 30000-39999)
- Reduces query time from 10+ seconds to <1ms for kind+author+d-tag queries
- Optimizes WouldReplaceEvent() for faster event replacement checks
Fixes#29
## Changes
- `pkg/database/query-addressable.go` - New file with fast path lookup logic
- `pkg/database/query-addressable_test.go` - Tests for the optimization
- `pkg/database/save-event.go` - Writes AddressableEvent index, optimizes WouldReplaceEvent
- `pkg/database/query-events.go` - Integrates fast path at start of QueryEventsWithOptions
- `pkg/database/get-indexes-for-event.go` - Minor refactor (variable rename)
## Test plan
- [x] All existing database tests pass
- [x] New tests added for addressable event queries
- [x] Tests cover: valid/invalid query patterns, not found case, event replacement
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: woikos <woikos@users.noreply.github.com>
Reviewed-on: https://git.nostrdev.com/mleku/next.orly.dev/pulls/30
Problem: Queries with kinds + authors + d-tags take 10+ seconds
Root cause: Using TagKindPubkey index requires timestamp iteration
Solution: Use AddressableEvent index for direct O(1) lookup
Plan covers:
- Phase 1: Enable AddressableEvent index writes on save
- Phase 2: Add fast path query for NIP-33 lookups
- Phase 3: Integrate into QueryEvents flow
- Phase 4: Optimize WouldReplaceEvent
- Phase 5: Handle index updates on replace
- Migration strategy for existing data
Expected improvement: 10+ seconds → <1ms
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use pre-built dockurr/strfry image instead of building from source
- Fix strfry.conf format to match strfry 1.0.4 syntax
- Fix Dockerfile.orly to build both relay and sync binaries
- Use GOTOOLCHAIN=auto to handle Go version requirements
- Remove healthcheck dependencies to prevent startup blocking
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use eventenvelope.NewResultWith() to properly format EVENT messages
with subscription ID, matching the expected format: ["EVENT", sub_id, event]
Previously SendEvent was sending just the raw event which caused JSON
parsing errors on the receiving side.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add have_ids, need_ids, complete fields to NegOpenResponse proto
- Fix ID encoding in server: decode hex strings to binary before sending
- Fix event sending order: send NEG-MSG response before EVENT envelopes
- Client now waits for expected events after reconciliation completes
- Store received events from peer in sync client message loop
This enables bidirectional event sync via NIP-77 negentropy. The server
can now push events it has that the client needs, in addition to the
client pushing events to the server.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement sendEventsForIDs to actually send events via EVENT envelopes
- Previously this was a TODO stub that only logged "would send"
- Server now fetches and sends identified "have" events to clients
Files modified:
- pkg/version/version: Bump to v0.55.6
- app/handle-negentropy.go: Implement sendEventsForIDs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>