@ -9,6 +9,7 @@ import (
"github.com/coder/websocket"
"github.com/coder/websocket"
"lol.mleku.dev/chk"
"lol.mleku.dev/chk"
"lol.mleku.dev/log"
"lol.mleku.dev/log"
"next.orly.dev/pkg/acl"
"next.orly.dev/pkg/encoders/envelopes/eventenvelope"
"next.orly.dev/pkg/encoders/envelopes/eventenvelope"
"next.orly.dev/pkg/encoders/event"
"next.orly.dev/pkg/encoders/event"
"next.orly.dev/pkg/encoders/filter"
"next.orly.dev/pkg/encoders/filter"
@ -211,68 +212,96 @@ func (p *P) Deliver(ev *event.E) {
break
break
}
}
}
}
}
}
if ! allowed {
if ! allowed {
log . D . F ( "subscription delivery DENIED for privileged event %s to %s (auth mismatch)" ,
log . D . F ( "subscription delivery DENIED for privileged event %s to %s (auth mismatch)" ,
hex . Enc ( ev . ID ) , d . sub . remote )
hex . Enc ( ev . ID ) , d . sub . remote )
// Skip delivery for this subscriber
// Skip delivery for this subscriber
continue
continue
}
}
}
}
var res * eventenvelope . Result
// Check for private tags - only deliver to authorized users
if res , err = eventenvelope . NewResultWith ( d . id , ev ) ; chk . E ( err ) {
if ev . Tags != nil && ev . Tags . Len ( ) > 0 {
log . E . F ( "failed to create event envelope for %s to %s: %v" ,
hasPrivateTag := false
hex . Enc ( ev . ID ) , d . sub . remote , err )
var privatePubkey [ ] byte
continue
}
for _ , t := range * ev . Tags {
if t . Len ( ) >= 2 {
// Log delivery attempt
keyBytes := t . Key ( )
msgData := res . Marshal ( nil )
if len ( keyBytes ) == 7 && string ( keyBytes ) == "private" {
log . D . F ( "attempting delivery of event %s (kind=%d, len=%d) to subscription %s @ %s" ,
hasPrivateTag = true
hex . Enc ( ev . ID ) , ev . Kind , len ( msgData ) , d . id , d . sub . remote )
privatePubkey = t . Value ( )
break
// Use a separate context with timeout for writes to prevent race conditions
}
// where the publisher context gets cancelled while writing events
}
writeCtx , cancel := context . WithTimeout (
}
context . Background ( ) , DefaultWriteTimeout ,
)
if hasPrivateTag {
defer cancel ( )
canSeePrivate := p . canSeePrivateEvent ( d . sub . AuthedPubkey , privatePubkey , d . sub . remote )
if ! canSeePrivate {
deliveryStart := time . Now ( )
log . D . F ( "subscription delivery DENIED for private event %s to %s (unauthorized)" ,
if err = d . w . Write (
hex . Enc ( ev . ID ) , d . sub . remote )
writeCtx , websocket . MessageText , msgData ,
continue
) ; err != nil {
}
deliveryDuration := time . Since ( deliveryStart )
log . D . F ( "subscription delivery ALLOWED for private event %s to %s (authorized)" ,
hex . Enc ( ev . ID ) , d . sub . remote )
// Log detailed failure information
}
log . E . F ( "subscription delivery FAILED: event=%s to=%s sub=%s duration=%v error=%v" ,
}
hex . Enc ( ev . ID ) , d . sub . remote , d . id , deliveryDuration , err )
var res * eventenvelope . Result
// Check for timeout specifically
if res , err = eventenvelope . NewResultWith ( d . id , ev ) ; chk . E ( err ) {
if writeCtx . Err ( ) != nil {
log . E . F ( "failed to create event envelope for %s to %s: %v" ,
log . E . F ( "subscription delivery TIMEOUT: event=%s to=%s after %v (limit=%v)" ,
hex . Enc ( ev . ID ) , d . sub . remote , err )
hex . Enc ( ev . ID ) , d . sub . remote , deliveryDuration , DefaultWriteTimeout )
continue
}
}
// Log connection cleanup
// Log delivery attempt
log . D . F ( "removing failed subscriber connection: %s" , d . sub . remote )
msgData := res . Marshal ( nil )
log . D . F ( "attempting delivery of event %s (kind=%d, len=%d) to subscription %s @ %s" ,
// On error, remove the subscriber connection safely
hex . Enc ( ev . ID ) , ev . Kind , len ( msgData ) , d . id , d . sub . remote )
p . removeSubscriber ( d . w )
_ = d . w . CloseNow ( )
// Use a separate context with timeout for writes to prevent race conditions
continue
// where the publisher context gets cancelled while writing events
}
writeCtx , cancel := context . WithTimeout (
context . Background ( ) , DefaultWriteTimeout ,
deliveryDuration := time . Since ( deliveryStart )
)
log . D . F ( "subscription delivery SUCCESS: event=%s to=%s sub=%s duration=%v len=%d" ,
defer cancel ( )
hex . Enc ( ev . ID ) , d . sub . remote , d . id , deliveryDuration , len ( msgData ) )
deliveryStart := time . Now ( )
// Log slow deliveries for performance monitoring
if err = d . w . Write (
if deliveryDuration > time . Millisecond * 50 {
writeCtx , websocket . MessageText , msgData ,
log . D . F ( "SLOW subscription delivery: event=%s to=%s duration=%v (>50ms)" ,
) ; err != nil {
hex . Enc ( ev . ID ) , d . sub . remote , deliveryDuration )
deliveryDuration := time . Since ( deliveryStart )
}
// Log detailed failure information
log . E . F ( "subscription delivery FAILED: event=%s to=%s sub=%s duration=%v error=%v" ,
hex . Enc ( ev . ID ) , d . sub . remote , d . id , deliveryDuration , err )
// Check for timeout specifically
if writeCtx . Err ( ) != nil {
log . E . F ( "subscription delivery TIMEOUT: event=%s to=%s after %v (limit=%v)" ,
hex . Enc ( ev . ID ) , d . sub . remote , deliveryDuration , DefaultWriteTimeout )
}
// Log connection cleanup
log . D . F ( "removing failed subscriber connection: %s" , d . sub . remote )
// On error, remove the subscriber connection safely
p . removeSubscriber ( d . w )
_ = d . w . CloseNow ( )
continue
}
deliveryDuration := time . Since ( deliveryStart )
log . D . F ( "subscription delivery SUCCESS: event=%s to=%s sub=%s duration=%v len=%d" ,
hex . Enc ( ev . ID ) , d . sub . remote , d . id , deliveryDuration , len ( msgData ) )
// Log slow deliveries for performance monitoring
if deliveryDuration > time . Millisecond * 50 {
log . D . F ( "SLOW subscription delivery: event=%s to=%s duration=%v (>50ms)" ,
hex . Enc ( ev . ID ) , d . sub . remote , deliveryDuration )
}
}
}
}
}
@ -299,3 +328,25 @@ func (p *P) removeSubscriber(ws *websocket.Conn) {
clear ( p . Map [ ws ] )
clear ( p . Map [ ws ] )
delete ( p . Map , ws )
delete ( p . Map , ws )
}
}
// canSeePrivateEvent checks if the authenticated user can see an event with a private tag
func ( p * P ) canSeePrivateEvent ( authedPubkey , privatePubkey [ ] byte , remote string ) ( canSee bool ) {
// If no authenticated user, deny access
if len ( authedPubkey ) == 0 {
return false
}
// If the authenticated user matches the private tag pubkey, allow access
if len ( privatePubkey ) > 0 && utils . FastEqual ( authedPubkey , privatePubkey ) {
return true
}
// Check if user is an admin or owner (they can see all private events)
accessLevel := acl . Registry . GetAccessLevel ( authedPubkey , remote )
if accessLevel == "admin" || accessLevel == "owner" {
return true
}
// Default deny
return false
}