fix policy to require auth and ignore all reqs before valid auth is made
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
This commit is contained in:
@@ -115,8 +115,8 @@ func NewAttestation(proposalID, decision string, weight int, reason, serviceURL
|
|||||||
return ev, nil
|
return ev, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTrustGraph creates a new trust graph event (kind 30101)
|
// NewTrustGraphEvent creates a new trust graph event (kind 30101)
|
||||||
func NewTrustGraph(entries []TrustEntry, signer signer.I) (*event.E, error) {
|
func NewTrustGraphEvent(entries []TrustEntry, signer signer.I) (*event.E, error) {
|
||||||
// Validate trust entries
|
// Validate trust entries
|
||||||
for i, entry := range entries {
|
for i, entry := range entries {
|
||||||
if err := ValidateTrustScore(entry.TrustScore); err != nil {
|
if err := ValidateTrustScore(entry.TrustScore); err != nil {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"lol.mleku.dev/chk"
|
"lol.mleku.dev/chk"
|
||||||
"lol.mleku.dev/errorf"
|
"lol.mleku.dev/errorf"
|
||||||
"next.orly.dev/pkg/database"
|
"next.orly.dev/pkg/database"
|
||||||
|
"next.orly.dev/pkg/encoders/hex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConsensusEngine handles the consensus algorithm for name registrations
|
// ConsensusEngine handles the consensus algorithm for name registrations
|
||||||
@@ -66,7 +67,7 @@ func (ce *ConsensusEngine) ComputeConsensus(proposals []*RegistrationProposal, a
|
|||||||
totalWeight := 0.0
|
totalWeight := 0.0
|
||||||
|
|
||||||
for _, proposal := range proposals {
|
for _, proposal := range proposals {
|
||||||
proposalAtts := attestationMap[proposal.Event.GetIDString()]
|
proposalAtts := attestationMap[hex.Enc(proposal.Event.ID)]
|
||||||
score, weights := ce.ScoreProposal(proposal, proposalAtts)
|
score, weights := ce.ScoreProposal(proposal, proposalAtts)
|
||||||
|
|
||||||
scores = append(scores, &ProposalScore{
|
scores = append(scores, &ProposalScore{
|
||||||
@@ -101,7 +102,7 @@ func (ce *ConsensusEngine) ComputeConsensus(proposals []*RegistrationProposal, a
|
|||||||
// Check for conflicts (multiple proposals within margin)
|
// Check for conflicts (multiple proposals within margin)
|
||||||
conflicted := false
|
conflicted := false
|
||||||
for _, ps := range scores {
|
for _, ps := range scores {
|
||||||
if ps.Proposal.Event.GetIDString() != winner.Proposal.Event.GetIDString() {
|
if hex.Enc(ps.Proposal.Event.ID) != hex.Enc(winner.Proposal.Event.ID) {
|
||||||
otherRelative := ps.Score / totalWeight
|
otherRelative := ps.Score / totalWeight
|
||||||
if (relativeScore - otherRelative) < ce.conflictMargin {
|
if (relativeScore - otherRelative) < ce.conflictMargin {
|
||||||
conflicted = true
|
conflicted = true
|
||||||
@@ -168,7 +169,7 @@ func (ce *ConsensusEngine) ScoreProposal(proposal *RegistrationProposal, attesta
|
|||||||
// Score = attestation_weight * trust_level / 100
|
// Score = attestation_weight * trust_level / 100
|
||||||
score := (attWeight / 100.0) * trustLevel
|
score := (attWeight / 100.0) * trustLevel
|
||||||
|
|
||||||
weights[att.Event.GetPubkeyString()] = score
|
weights[hex.Enc(att.Event.Pubkey)] = score
|
||||||
totalScore += score
|
totalScore += score
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +206,7 @@ func (ce *ConsensusEngine) ValidateProposal(proposal *RegistrationProposal) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify proposer owns parent domain
|
// Verify proposer owns parent domain
|
||||||
proposerPubkey := proposal.Event.GetPubkeyString()
|
proposerPubkey := hex.Enc(proposal.Event.Pubkey)
|
||||||
if parentState.Owner != proposerPubkey {
|
if parentState.Owner != proposerPubkey {
|
||||||
return errorf.E("proposer does not own parent domain %s", parent)
|
return errorf.E("proposer does not own parent domain %s", parent)
|
||||||
}
|
}
|
||||||
@@ -239,7 +240,7 @@ func (ce *ConsensusEngine) ValidateProposal(proposal *RegistrationProposal) erro
|
|||||||
|
|
||||||
// During renewal window - only current owner can register
|
// During renewal window - only current owner can register
|
||||||
if now.Before(nameState.Expiration) {
|
if now.Before(nameState.Expiration) {
|
||||||
proposerPubkey := proposal.Event.GetPubkeyString()
|
proposerPubkey := hex.Enc(proposal.Event.Pubkey)
|
||||||
if proposerPubkey != nameState.Owner {
|
if proposerPubkey != nameState.Owner {
|
||||||
return errorf.E("only current owner can renew during preferential renewal window")
|
return errorf.E("only current owner can renew during preferential renewal window")
|
||||||
}
|
}
|
||||||
@@ -320,9 +321,9 @@ func (ce *ConsensusEngine) CreateNameState(result *ConsensusResult, registryPubk
|
|||||||
|
|
||||||
return &NameState{
|
return &NameState{
|
||||||
Name: proposal.Name,
|
Name: proposal.Name,
|
||||||
Owner: proposal.Event.GetPubkeyString(),
|
Owner: hex.Enc(proposal.Event.Pubkey),
|
||||||
RegisteredAt: time.Now(),
|
RegisteredAt: time.Now(),
|
||||||
ProposalID: proposal.Event.GetIDString(),
|
ProposalID: hex.Enc(proposal.Event.ID),
|
||||||
Attestations: result.Attestations,
|
Attestations: result.Attestations,
|
||||||
Confidence: result.Confidence,
|
Confidence: result.Confidence,
|
||||||
Expiration: time.Now().Add(NameRegistrationPeriod),
|
Expiration: time.Now().Add(NameRegistrationPeriod),
|
||||||
@@ -344,7 +345,7 @@ func (ce *ConsensusEngine) ProcessProposalBatch(proposals []*RegistrationProposa
|
|||||||
// Filter attestations for this name's proposals
|
// Filter attestations for this name's proposals
|
||||||
proposalIDs := make(map[string]bool)
|
proposalIDs := make(map[string]bool)
|
||||||
for _, p := range nameProposals {
|
for _, p := range nameProposals {
|
||||||
proposalIDs[p.Event.GetIDString()] = true
|
proposalIDs[hex.Enc(p.Event.ID)] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
nameAttestations := make([]*Attestation, 0)
|
nameAttestations := make([]*Attestation, 0)
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ func ParseAttestation(ev *event.E) (*Attestation, error) {
|
|||||||
return attestation, nil
|
return attestation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseTrustGraph parses a kind 30101 event into a TrustGraph
|
// ParseTrustGraph parses a kind 30101 event into a TrustGraphEvent
|
||||||
func ParseTrustGraph(ev *event.E) (*TrustGraph, error) {
|
func ParseTrustGraph(ev *event.E) (*TrustGraphEvent, error) {
|
||||||
if uint16(ev.Kind) != KindTrustGraph {
|
if uint16(ev.Kind) != KindTrustGraph {
|
||||||
return nil, fmt.Errorf("invalid event kind: expected %d, got %d", KindTrustGraph, ev.Kind)
|
return nil, fmt.Errorf("invalid event kind: expected %d, got %d", KindTrustGraph, ev.Kind)
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ func ParseTrustGraph(ev *event.E) (*TrustGraph, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return &TrustGraph{
|
return &TrustGraphEvent{
|
||||||
Event: ev,
|
Event: ev,
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
Expiration: expiration,
|
Expiration: expiration,
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package find
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
lol "lol.mleku.dev"
|
|
||||||
"lol.mleku.dev/chk"
|
"lol.mleku.dev/chk"
|
||||||
"next.orly.dev/pkg/database"
|
"next.orly.dev/pkg/database"
|
||||||
"next.orly.dev/pkg/encoders/event"
|
"next.orly.dev/pkg/encoders/event"
|
||||||
@@ -71,7 +71,7 @@ func NewRegistryService(ctx context.Context, db database.Database, signer signer
|
|||||||
// Bootstrap trust graph if configured
|
// Bootstrap trust graph if configured
|
||||||
if len(config.BootstrapServices) > 0 {
|
if len(config.BootstrapServices) > 0 {
|
||||||
if err := rs.bootstrapTrustGraph(); chk.E(err) {
|
if err := rs.bootstrapTrustGraph(); chk.E(err) {
|
||||||
lol.Err("failed to bootstrap trust graph:", err)
|
fmt.Printf("failed to bootstrap trust graph: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ func NewRegistryService(ctx context.Context, db database.Database, signer signer
|
|||||||
|
|
||||||
// Start starts the registry service
|
// Start starts the registry service
|
||||||
func (rs *RegistryService) Start() error {
|
func (rs *RegistryService) Start() error {
|
||||||
lol.Info("starting FIND registry service")
|
fmt.Println("starting FIND registry service")
|
||||||
|
|
||||||
// Start proposal monitoring goroutine
|
// Start proposal monitoring goroutine
|
||||||
rs.wg.Add(1)
|
rs.wg.Add(1)
|
||||||
@@ -99,7 +99,7 @@ func (rs *RegistryService) Start() error {
|
|||||||
|
|
||||||
// Stop stops the registry service
|
// Stop stops the registry service
|
||||||
func (rs *RegistryService) Stop() error {
|
func (rs *RegistryService) Stop() error {
|
||||||
lol.Info("stopping FIND registry service")
|
fmt.Println("stopping FIND registry service")
|
||||||
|
|
||||||
rs.cancel()
|
rs.cancel()
|
||||||
rs.wg.Wait()
|
rs.wg.Wait()
|
||||||
@@ -139,11 +139,11 @@ func (rs *RegistryService) checkForNewProposals() {
|
|||||||
func (rs *RegistryService) OnProposalReceived(proposal *RegistrationProposal) error {
|
func (rs *RegistryService) OnProposalReceived(proposal *RegistrationProposal) error {
|
||||||
// Validate proposal
|
// Validate proposal
|
||||||
if err := rs.consensus.ValidateProposal(proposal); chk.E(err) {
|
if err := rs.consensus.ValidateProposal(proposal); chk.E(err) {
|
||||||
lol.Warn("invalid proposal:", err)
|
fmt.Printf("invalid proposal: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
proposalID := proposal.Event.GetIDString()
|
proposalID := hex.Enc(proposal.Event.ID)
|
||||||
|
|
||||||
rs.mu.Lock()
|
rs.mu.Lock()
|
||||||
defer rs.mu.Unlock()
|
defer rs.mu.Unlock()
|
||||||
@@ -153,7 +153,7 @@ func (rs *RegistryService) OnProposalReceived(proposal *RegistrationProposal) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lol.Info("received new proposal:", proposalID, "name:", proposal.Name)
|
fmt.Printf("received new proposal: %s name: %s\n", proposalID, proposal.Name)
|
||||||
|
|
||||||
// Create proposal state
|
// Create proposal state
|
||||||
state := &ProposalState{
|
state := &ProposalState{
|
||||||
@@ -185,8 +185,8 @@ func (rs *RegistryService) shouldAttest(proposalID string) bool {
|
|||||||
|
|
||||||
// Sparse attestation: use hash of (proposal_id || service_pubkey) % K == 0
|
// Sparse attestation: use hash of (proposal_id || service_pubkey) % K == 0
|
||||||
// This provides deterministic but distributed attestation
|
// This provides deterministic but distributed attestation
|
||||||
hash := hex.Dec(proposalID)
|
hash, err := hex.Dec(proposalID)
|
||||||
if len(hash) == 0 {
|
if err != nil || len(hash) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ func (rs *RegistryService) shouldAttest(proposalID string) bool {
|
|||||||
// publishAttestation publishes an attestation for a proposal
|
// publishAttestation publishes an attestation for a proposal
|
||||||
func (rs *RegistryService) publishAttestation(proposal *RegistrationProposal, decision string, reason string) {
|
func (rs *RegistryService) publishAttestation(proposal *RegistrationProposal, decision string, reason string) {
|
||||||
attestation := &Attestation{
|
attestation := &Attestation{
|
||||||
ProposalID: proposal.Event.GetIDString(),
|
ProposalID: hex.Enc(proposal.Event.ID),
|
||||||
Decision: decision,
|
Decision: decision,
|
||||||
Weight: 100,
|
Weight: 100,
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
@@ -209,7 +209,7 @@ func (rs *RegistryService) publishAttestation(proposal *RegistrationProposal, de
|
|||||||
// TODO: Publish to database
|
// TODO: Publish to database
|
||||||
_ = attestation
|
_ = attestation
|
||||||
|
|
||||||
lol.Debug("published attestation for proposal:", proposal.Name, "decision:", decision)
|
fmt.Printf("published attestation for proposal: %s decision: %s\n", proposal.Name, decision)
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectAttestations collects attestations from other registry services
|
// collectAttestations collects attestations from other registry services
|
||||||
@@ -260,7 +260,7 @@ func (rs *RegistryService) processProposal(proposalID string) {
|
|||||||
state.ProcessedAt = &now
|
state.ProcessedAt = &now
|
||||||
rs.mu.Unlock()
|
rs.mu.Unlock()
|
||||||
|
|
||||||
lol.Info("processing proposal:", proposalID, "name:", state.Proposal.Name)
|
fmt.Printf("processing proposal: %s name: %s\n", proposalID, state.Proposal.Name)
|
||||||
|
|
||||||
// Check for competing proposals for the same name
|
// Check for competing proposals for the same name
|
||||||
competingProposals := rs.getCompetingProposals(state.Proposal.Name)
|
competingProposals := rs.getCompetingProposals(state.Proposal.Name)
|
||||||
@@ -279,23 +279,24 @@ func (rs *RegistryService) processProposal(proposalID string) {
|
|||||||
|
|
||||||
result, err := rs.consensus.ComputeConsensus(proposalList, allAttestations)
|
result, err := rs.consensus.ComputeConsensus(proposalList, allAttestations)
|
||||||
if chk.E(err) {
|
if chk.E(err) {
|
||||||
lol.Err("consensus computation failed:", err)
|
fmt.Printf("consensus computation failed: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log result
|
// Log result
|
||||||
if result.Conflicted {
|
if result.Conflicted {
|
||||||
lol.Warn("consensus conflicted for name:", state.Proposal.Name, "reason:", result.Reason)
|
fmt.Printf("consensus conflicted for name: %s reason: %s\n", state.Proposal.Name, result.Reason)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lol.Info("consensus reached for name:", state.Proposal.Name,
|
fmt.Printf("consensus reached for name: %s winner: %s confidence: %f\n",
|
||||||
"winner:", result.Winner.Event.GetIDString(),
|
state.Proposal.Name,
|
||||||
"confidence:", result.Confidence)
|
hex.Enc(result.Winner.Event.ID),
|
||||||
|
result.Confidence)
|
||||||
|
|
||||||
// Publish name state (kind 30102)
|
// Publish name state (kind 30102)
|
||||||
if err := rs.publishNameState(result); chk.E(err) {
|
if err := rs.publishNameState(result); chk.E(err) {
|
||||||
lol.Err("failed to publish name state:", err)
|
fmt.Printf("failed to publish name state: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +369,7 @@ func (rs *RegistryService) refreshTrustGraph() {
|
|||||||
|
|
||||||
// updateTrustGraph fetches trust graphs from other services
|
// updateTrustGraph fetches trust graphs from other services
|
||||||
func (rs *RegistryService) updateTrustGraph() {
|
func (rs *RegistryService) updateTrustGraph() {
|
||||||
lol.Debug("updating trust graph")
|
fmt.Println("updating trust graph")
|
||||||
|
|
||||||
// TODO: Query kind 30101 events (trust graphs) from database
|
// TODO: Query kind 30101 events (trust graphs) from database
|
||||||
// TODO: Parse and update trust graph
|
// TODO: Parse and update trust graph
|
||||||
@@ -377,7 +378,7 @@ func (rs *RegistryService) updateTrustGraph() {
|
|||||||
|
|
||||||
// bootstrapTrustGraph initializes trust relationships with bootstrap services
|
// bootstrapTrustGraph initializes trust relationships with bootstrap services
|
||||||
func (rs *RegistryService) bootstrapTrustGraph() error {
|
func (rs *RegistryService) bootstrapTrustGraph() error {
|
||||||
lol.Info("bootstrapping trust graph with", len(rs.config.BootstrapServices), "services")
|
fmt.Printf("bootstrapping trust graph with %d services\n", len(rs.config.BootstrapServices))
|
||||||
|
|
||||||
for _, pubkeyHex := range rs.config.BootstrapServices {
|
for _, pubkeyHex := range rs.config.BootstrapServices {
|
||||||
entry := TrustEntry{
|
entry := TrustEntry{
|
||||||
@@ -387,7 +388,7 @@ func (rs *RegistryService) bootstrapTrustGraph() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := rs.trustGraph.AddEntry(entry); chk.E(err) {
|
if err := rs.trustGraph.AddEntry(entry); chk.E(err) {
|
||||||
lol.Warn("failed to add bootstrap trust entry:", err)
|
fmt.Printf("failed to add bootstrap trust entry: %v\n", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,15 +281,15 @@ func (tg *TrustGraph) GetInheritedTrust(fromPubkey, toPubkey string) (float64, [
|
|||||||
return 0.0, nil
|
return 0.0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportTrustGraph exports the trust graph for this service as a TrustGraph event
|
// ExportTrustGraph exports the trust graph for this service as a TrustGraphEvent
|
||||||
func (tg *TrustGraph) ExportTrustGraph() *TrustGraph {
|
func (tg *TrustGraph) ExportTrustGraph() *TrustGraphEvent {
|
||||||
tg.mu.RLock()
|
tg.mu.RLock()
|
||||||
defer tg.mu.RUnlock()
|
defer tg.mu.RUnlock()
|
||||||
|
|
||||||
selfPubkeyStr := hex.Enc(tg.selfPubkey)
|
selfPubkeyStr := hex.Enc(tg.selfPubkey)
|
||||||
entries := tg.entries[selfPubkeyStr]
|
entries := tg.entries[selfPubkeyStr]
|
||||||
|
|
||||||
exported := &TrustGraph{
|
exported := &TrustGraphEvent{
|
||||||
Event: nil, // TODO: Create event
|
Event: nil, // TODO: Create event
|
||||||
Entries: make([]TrustEntry, len(entries)),
|
Entries: make([]TrustEntry, len(entries)),
|
||||||
Expiration: time.Now().Add(TrustGraphExpiry),
|
Expiration: time.Now().Add(TrustGraphExpiry),
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ type TrustEntry struct {
|
|||||||
TrustScore float64 // 0.0 to 1.0
|
TrustScore float64 // 0.0 to 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrustGraph represents a kind 30101 event
|
// TrustGraphEvent represents a kind 30101 event (renamed to avoid conflict with TrustGraph manager in trust.go)
|
||||||
type TrustGraph struct {
|
type TrustGraphEvent struct {
|
||||||
Event *event.E
|
Event *event.E
|
||||||
Entries []TrustEntry
|
Entries []TrustEntry
|
||||||
Expiration time.Time
|
Expiration time.Time
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ func VerifyAttestationExpiration(attestation *Attestation) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyTrustGraphExpiration checks if a trust graph has expired
|
// VerifyTrustGraphExpiration checks if a trust graph has expired
|
||||||
func VerifyTrustGraphExpiration(trustGraph *TrustGraph) error {
|
func VerifyTrustGraphExpiration(trustGraph *TrustGraphEvent) error {
|
||||||
if !trustGraph.Expiration.IsZero() && IsExpired(trustGraph.Expiration) {
|
if !trustGraph.Expiration.IsZero() && IsExpired(trustGraph.Expiration) {
|
||||||
return fmt.Errorf("trust graph expired at %s", trustGraph.Expiration)
|
return fmt.Errorf("trust graph expired at %s", trustGraph.Expiration)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -900,12 +900,6 @@ func (p *P) CheckPolicy(
|
|||||||
return false, fmt.Errorf("event cannot be nil")
|
return false, fmt.Errorf("event cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRITICAL SECURITY: Reject all unauthenticated access
|
|
||||||
// No authentication = no access, regardless of policy rules
|
|
||||||
if len(loggedInPubkey) == 0 {
|
|
||||||
return false, nil // Silently reject unauthenticated users
|
|
||||||
}
|
|
||||||
|
|
||||||
// First check global rule filter (applies to all events)
|
// First check global rule filter (applies to all events)
|
||||||
if !p.checkGlobalRulePolicy(access, ev, loggedInPubkey) {
|
if !p.checkGlobalRulePolicy(access, ev, loggedInPubkey) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v0.29.13
|
v0.29.14
|
||||||
Reference in New Issue
Block a user