- 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>
- 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
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>
- 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
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>
- Add MaxEvents config option to negentropy manager
- Increase default sync limit from 100,000 to 1,000,000 events
- Ensures full database sync for relays with 200k+ events
Files modified:
- pkg/sync/negentropy/manager.go: Add MaxEvents config, use configurable limit
- pkg/sync/negentropy/server/service.go: Increase hardcoded limit to 1M
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds ORLY_SYNC_NEGENTROPY_FILTER env var for specifying a JSON-encoded
nostr filter for selective sync. The filter is used both when building
local storage for comparison and in the NEG-OPEN message sent to peers.
Example usage:
ORLY_SYNC_NEGENTROPY_FILTER='{"kinds":[1,6,7,30023]}'
ORLY_SYNC_NEGENTROPY_FILTER='{"authors":["abc123..."],"since":1700000000}'
This allows syncing only specific event types between relays instead of
the full event set.
Files modified:
- cmd/orly-sync-negentropy/config.go: Add FilterJSON config and parsing
- cmd/orly-sync-negentropy/main.go: Pass filter to manager config
- pkg/sync/negentropy/manager.go: Add Filter to Config, use in buildStorage and NEG-OPEN
- pkg/version/version: Bump to v0.55.3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ACL: Mark service ready immediately after gRPC server starts
- ACL: Run Configure() in background goroutine (follow list loading)
- Launcher: Actually call gRPC Ready() endpoint instead of just TCP port check
- Launcher: Increase ACL ready timeout from 30s to 120s as fallback
This fixes the issue where relay would timeout waiting for ACL because
the launcher only checked if the TCP port was open, but the ACL service's
Ready() was returning false until Configure() completed (which takes
minutes for large follow lists).
Now ACL marks itself ready immediately so the relay can start while
follow lists continue loading in the background.
Files modified:
- cmd/orly-acl/main.go: Restructure startup to be async
- cmd/orly-launcher/config.go: Increase ACL timeout to 120s
- cmd/orly-launcher/supervisor.go: Add gRPC Ready() check
- pkg/version/version: Bump to v0.55.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove debug 100 iteration limit from GetSerialsByRange
The limit was a debug safety check that should have been removed.
This was capping all range queries to 100 results, causing negentropy
sync to only see 100 events instead of all events.
- Fix ACL service startup to listen immediately before Configure
The ACL server now starts the gRPC listener immediately after database
ready, then runs Configure in the background. This prevents the
launcher from timing out while waiting for ACL to load follow lists.
- Add SetReady method to ACL service for proper ready signaling
Files modified:
- pkg/database/get-serials-by-range.go: Remove debug iteration limit
- cmd/orly-acl/main.go: Start gRPC server before Configure
- cmd/orly-acl/service.go: Add ready field and SetReady method
- pkg/version/version: Bump to v0.55.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add four independent gRPC sync service binaries:
- orly-sync-distributed: Serial-based peer-to-peer sync
- orly-sync-cluster: Cluster replication with persistent state
- orly-sync-relaygroup: Relay group config discovery (Kind 39105)
- orly-sync-negentropy: NIP-77 efficient set reconciliation
- Implement NIP-77 negentropy protocol for relay-to-relay sync
- Add push-based event transfer for negentropy sync
- Add client-facing NIP-77 WebSocket support (NEG-OPEN/MSG/CLOSE)
- Add deployment scripts with symlink-based versioning
- Add Makefile targets for quick deployment and rollback
- Refactor existing sync code into modular service packages
- Add proto definitions for all sync services
- Integrate negentropy service into orly-launcher supervisor
- Advertise NIP-77 support in relay info document
Files modified:
- Makefile: Add sync service build targets and deployment commands
- README.md: Document NIP-77 support
- app/config/config.go: Add negentropy configuration options
- app/handle-message.go: Route NEG-* envelopes to negentropy handler
- app/handle-negentropy.go: New file for NIP-77 WebSocket handling
- app/handle-relayinfo.go: Advertise NIP-77 support
- cmd/orly-launcher/: Add negentropy service management
- cmd/orly-sync-*/: New service binaries
- main.go: Add negentropy gRPC client initialization
- pkg/proto/orlysync/: New proto definitions and generated code
- pkg/sync/*/: Refactored sync packages with gRPC services
- scripts/deploy-orly.sh: New symlink-based deployment script
- scripts/build-and-deploy.sh: New build and deploy workflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change Follows, Managed, and Curating ACL structs to use database.Database
interface instead of concrete *database.D type
- Add type assertions for ManagedACL and CuratingACL initialization since
they require Badger-specific APIs
- Log warning when running managed/curating ACL with non-Badger backend
- Update managed_minimal_test.go to use new field name
Files modified:
- pkg/acl/follows.go: Use db database.Database field, replace f.D with f.db
- pkg/acl/managed.go: Use db database.Database with type assertion for ManagedACL
- pkg/acl/curating.go: Use db database.Database with type assertion for CuratingACL
- pkg/acl/managed_minimal_test.go: Update test to use db field
- pkg/version/version: Bump to v0.53.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add query semaphore limiting concurrent database queries to 3
- Reuse single iterator in FetchEventsBySerials instead of one per serial
- Disable expensive e-tag fallback lookup in deletion processing
- Add empty ID validation in access tracker loop
- Reduce log spam from GetSerialById empty ID errors
These changes reduce memory usage from ~5GB to ~150MB under load by
limiting concurrent Badger iterators which consume significant memory.
Files modified:
- pkg/database/database.go: Add query semaphore with acquire/release
- pkg/database/fetch-events-by-serials.go: Reuse iterator for sev lookups
- pkg/database/query-events.go: Add semaphore, disable e-tag fallback
- pkg/database/get-serial-by-id.go: Don't log empty ID errors
- app/handle-req.go: Validate event ID before GetSerialById
- pkg/version/version: Bump to v0.52.17
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previous: 10MB read + 10MB write = 20MB per connection
New: 64KB read + 64KB write = 128KB per connection
With 100 connections:
- Before: 2GB just for buffers
- After: 12.5MB for buffers
The read limit (SetReadLimit) still allows 10MB messages, but the
internal buffers don't need to be that large.
Files modified:
- app/handle-websocket.go: Reduce buffer sizes
- pkg/version/version: Bump to v0.52.12
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ORLY_QUERY_RESULT_LIMIT config (default 256)
- Enforce limit on each REQ filter before database query
- Caps client limit if it exceeds server limit
- Applies server limit if client sends no limit
This prevents unbounded queries from loading millions of events
into memory and causing OOM kills.
Files modified:
- app/config/config.go: Add QueryResultLimit config
- app/handle-req.go: Enforce limit on each filter
- pkg/version/version: Bump to v0.52.11
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ORLY_MAX_CONN_PER_IP config option (default 25, hard limit 40)
- Track connections per IP in Server struct
- Reject new connections with HTTP 429 when limit exceeded
- Properly decrement count when connections close
This prevents a single IP from opening unlimited connections and
exhausting server memory/goroutines.
Files modified:
- app/config/config.go: Add MaxConnectionsPerIP config
- app/server.go: Add connPerIP tracking map
- app/main.go: Initialize connPerIP map
- app/handle-websocket.go: Implement per-IP limit check
- pkg/version/version: Bump to v0.52.10
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Disable goroutine that deleted expired events during query processing
- This was causing "assignment to entry in nil map" Badger panics under load
- Expired events will remain until proper background cleanup is implemented
- Added TODO comments explaining the issue and fix needed
Files modified:
- pkg/database/query-events.go: Disable inline expired event deletion
- pkg/version/version: Bump to v0.52.9
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change ORLY_GC_ENABLED default from true to false
- Mark GC as EXPERIMENTAL in config usage string
- Add detailed TODOs documenting Badger race condition issues
- GC triggers "assignment to entry in nil map" panics under concurrent load
Files modified:
- app/config/config.go: Default GC to false, add TODO comments
- pkg/storage/gc.go: Add detailed implementation TODOs
- pkg/version/version: Bump to v0.52.8
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change default event query window from 30 days to 5 years in web UI
- Remove 6-month fallback retry logic (no longer needed with larger window)
- Simplifies fetchAllEvents function in nostr.js
Files modified:
- app/web/src/nostr.js: Extended time window from 30 days to 5 years
- app/web/dist/bundle.js: Rebuilt with changes
- pkg/version/version: Bump to v0.52.7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add port 7777 to list of known relay ports in config.js
- Prevents false-positive standalone mode detection
Files modified:
- app/web/src/config.js: Add 7777 to relay port list
- pkg/version/version: Bump to v0.52.6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add post-query filtering to return only latest version per (pubkey, kind, d-tag)
- Delete older versions on save for kinds 30000-39999 in Neo4j backend
- QueryAllVersions bypasses filtering for recovery UI compatibility
- Badger continues to keep old versions (filtered at query time)
Files modified:
- pkg/neo4j/query-events.go: Add replaceable event filtering logic
- pkg/neo4j/save-event.go: Add deleteOlderParameterizedReplaceable helper
- pkg/version/version: Bump to v0.52.5
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add standalone mode for dashboard to connect to any ORLY relay
- Implement relay switcher dropdown in header for standalone mode
- Add mobile drawer sidebar at 640px breakpoint with hamburger menu
- Add dedicated fallback pool for profile/relay list/contact list fetches
- Fix relay URL display to show host instead of NIP-11 name
- Add filter validation and defensive checks in event fetching
- Auto-expand search window from 30 days to 6 months on few results
- Add CORS support for API endpoints with configurable origins
- Fetch user relay list (NIP-65 kind 10002) and contact list on login
- Fix light mode user name color visibility in header
Files modified:
- app/config/config.go: Add CORS configuration options
- app/server.go: Add CORS middleware for API endpoints
- app/handle-relayinfo.go: Include CORS in relay info
- app/web/src/config.js: New config module for standalone mode
- app/web/src/stores.js: Add relay URL and standalone mode stores
- app/web/src/nostr.js: Add fallback pool, filter validation, relay/contact fetch
- app/web/src/Header.svelte: Relay dropdown, mobile menu, static indicator
- app/web/src/Sidebar.svelte: Mobile drawer mode with overlay
- app/web/src/App.svelte: Relay switching, mobile menu state, NIP-65 fetch
- app/web/src/api.js: Use configurable base URL
- app/web/src/constants.js: Add fallback relays, dynamic relay URLs
- cmd/dashboard-server/main.go: New standalone dashboard server
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>