From c59b89c3856489827261dcef667ee5866e725195 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Thu, 23 Jul 2026 01:26:07 +0900 Subject: [PATCH] appview: stop ingesting spindle server / member records Signed-off-by: Seongmin Lee --- appview/ingester.go | 311 --------------------------------------- appview/oauth/handler.go | 44 ------ 2 files changed, 355 deletions(-) diff --git a/appview/ingester.go b/appview/ingester.go index cf2d6037..5ec92337 100644 --- a/appview/ingester.go +++ b/appview/ingester.go @@ -97,10 +97,6 @@ func (i *Ingester) Ingest() processFunc { err = i.ingestArtifact(ctx, e, l) case tangled.ActorProfileNSID: err = i.ingestProfile(ctx, e, l) - case tangled.SpindleMemberNSID: - err = i.ingestSpindleMember(ctx, e, l) - case tangled.SpindleNSID: - err = i.ingestSpindle(ctx, e, l) case tangled.KnotMemberNSID: err = i.ingestKnotMember(ctx, e, l) case tangled.KnotNSID: @@ -664,268 +660,6 @@ func (i *Ingester) ingestProfile(ctx context.Context, e *jmodels.Event, l *slog. return nil } -func (i *Ingester) ingestSpindleMember(ctx context.Context, e *jmodels.Event, l *slog.Logger) error { - did := e.Did - var err error - - l = l.With("handler", "ingestSpindleMember") - - switch e.Commit.Operation { - case jmodels.CommitOperationCreate, jmodels.CommitOperationUpdate: - raw := json.RawMessage(e.Commit.Record) - record := tangled.SpindleMember{} - err = json.Unmarshal(raw, &record) - if err != nil { - l.Error("invalid record", "err", err) - return err - } - - // only spindle owner can invite to spindles - ok, err := i.Enforcer.IsSpindleInviteAllowed(did, record.Instance) - if err != nil { - return fmt.Errorf("failed to check invite permission: %w", err) - } - if !ok { - if verifyErr := i.verifySpindle(ctx, record.Instance, did); verifyErr != nil { - return fmt.Errorf("invite denied and verify failed: %w", verifyErr) - } - ok, err = i.Enforcer.IsSpindleInviteAllowed(did, record.Instance) - if err != nil { - return fmt.Errorf("failed to re-check invite permission: %w", err) - } - if !ok { - return fmt.Errorf("invite denied for did %s on spindle %s", did, record.Instance) - } - } - - memberId, err := i.IdResolver.ResolveIdent(ctx, record.Subject) - if err != nil { - return err - } - - if memberId.Handle.IsInvalidHandle() { - return fmt.Errorf("invalid handle for member %s", record.Subject) - } - - existing, err := db.GetSpindleMembers(i.Db, - orm.FilterEq("did", did), - orm.FilterEq("rkey", e.Commit.RKey), - ) - if err != nil { - return fmt.Errorf("failed to look up existing member: %w", err) - } - if len(existing) > 1 { - return fmt.Errorf("multiple spindle members with rkey %s", e.Commit.RKey) - } - - tx, err := i.Db.Begin() - if err != nil { - return fmt.Errorf("failed to start txn: %w", err) - } - committed := false - defer func() { - if committed { - return - } - tx.Rollback() - i.Enforcer.E.LoadPolicy() - }() - - if len(existing) == 1 { - prev := existing[0] - if prev.Instance != record.Instance || prev.Subject != memberId.DID { - if err = db.RemoveSpindleMember(tx, - orm.FilterEq("did", did), - orm.FilterEq("rkey", e.Commit.RKey), - ); err != nil { - return fmt.Errorf("failed to remove stale row: %w", err) - } - if err = i.Enforcer.RemoveSpindleMember(prev.Instance, prev.Subject.String()); err != nil { - return fmt.Errorf("failed to remove stale ACL: %w", err) - } - } - } - - if err = db.AddSpindleMember(tx, models.SpindleMember{ - Did: syntax.DID(did), - Rkey: e.Commit.RKey, - Instance: record.Instance, - Subject: memberId.DID, - }); err != nil { - return fmt.Errorf("failed to add to db: %w", err) - } - - if err = i.Enforcer.AddSpindleMember(record.Instance, memberId.DID.String()); err != nil { - return fmt.Errorf("failed to update ACLs: %w", err) - } - - if err = tx.Commit(); err != nil { - return fmt.Errorf("failed to commit txn: %w", err) - } - - if err = i.Enforcer.E.SavePolicy(); err != nil { - return fmt.Errorf("failed to save ACLs: %w", err) - } - committed = true - - l.Info("upserted spindle member") - case jmodels.CommitOperationDelete: - rkey := e.Commit.RKey - - // get record from db first - members, err := db.GetSpindleMembers( - i.Db, - orm.FilterEq("did", did), - orm.FilterEq("rkey", rkey), - ) - if err != nil || len(members) != 1 { - return fmt.Errorf("failed to get member: %w, len(members) = %d", err, len(members)) - } - member := members[0] - - tx, err := i.Db.Begin() - if err != nil { - return fmt.Errorf("failed to start txn: %w", err) - } - committed := false - defer func() { - if committed { - return - } - tx.Rollback() - i.Enforcer.E.LoadPolicy() - }() - - // remove record by rkey && update enforcer - if err = db.RemoveSpindleMember( - tx, - orm.FilterEq("did", did), - orm.FilterEq("rkey", rkey), - ); err != nil { - return fmt.Errorf("failed to remove from db: %w", err) - } - - // update enforcer - err = i.Enforcer.RemoveSpindleMember(member.Instance, member.Subject.String()) - if err != nil { - return fmt.Errorf("failed to update ACLs: %w", err) - } - - if err = tx.Commit(); err != nil { - return fmt.Errorf("failed to commit txn: %w", err) - } - - if err = i.Enforcer.E.SavePolicy(); err != nil { - return fmt.Errorf("failed to save ACLs: %w", err) - } - committed = true - - l.Info("removed spindle member") - } - - return nil -} - -func (i *Ingester) ingestSpindle(ctx context.Context, e *jmodels.Event, l *slog.Logger) error { - did := e.Did - var err error - - l = l.With("handler", "ingestSpindle") - - switch e.Commit.Operation { - case jmodels.CommitOperationCreate, jmodels.CommitOperationUpdate: - raw := json.RawMessage(e.Commit.Record) - record := tangled.Spindle{} - err = json.Unmarshal(raw, &record) - if err != nil { - l.Error("invalid record", "err", err) - return err - } - - instance := e.Commit.RKey - - err := db.AddSpindle(i.Db, models.Spindle{ - Owner: syntax.DID(did), - Instance: instance, - }) - if err != nil { - l.Error("failed to add spindle to db", "err", err, "instance", instance) - return err - } - - if err := i.verifySpindle(ctx, instance, did); err != nil { - l.Warn("failed to verify spindle", "instance", instance, "did", did, "err", err) - } - - l.Info("ingested record", "instance", instance) - return nil - - case jmodels.CommitOperationDelete: - instance := e.Commit.RKey - - // get record from db first - spindles, err := db.GetSpindles( - ctx, - i.Db, - orm.FilterEq("owner", did), - orm.FilterEq("instance", instance), - ) - if err != nil || len(spindles) != 1 { - return fmt.Errorf("failed to get spindles: %w, len(spindles) = %d", err, len(spindles)) - } - spindle := spindles[0] - - tx, err := i.Db.Begin() - if err != nil { - return fmt.Errorf("failed to start txn: %w", err) - } - defer func() { - tx.Rollback() - i.Enforcer.E.LoadPolicy() - }() - - // remove spindle members first - err = db.RemoveSpindleMember( - tx, - orm.FilterEq("owner", did), - orm.FilterEq("instance", instance), - ) - if err != nil { - return fmt.Errorf("failed to remove spindle members: %w", err) - } - - err = db.DeleteSpindle( - tx, - orm.FilterEq("owner", did), - orm.FilterEq("instance", instance), - ) - if err != nil { - return fmt.Errorf("failed to delete spindle: %w", err) - } - - if spindle.Verified != nil { - err = i.Enforcer.RemoveSpindle(instance) - if err != nil { - return fmt.Errorf("failed to remove spindle from enforcer: %w", err) - } - } - - err = tx.Commit() - if err != nil { - return fmt.Errorf("failed to commit txn: %w", err) - } - - err = i.Enforcer.E.SavePolicy() - if err != nil { - return fmt.Errorf("failed to save ACLs: %w", err) - } - - l.Info("ingested record", "instance", instance) - } - - return nil -} - func (i *Ingester) ingestString(e *jmodels.Event, l *slog.Logger) error { did := e.Did rkey := e.Commit.RKey @@ -1281,37 +1015,6 @@ func (i *Ingester) verifyKnot(ctx context.Context, domain, did string) error { return serververify.MarkKnotVerified(i.Db, i.Enforcer, domain, did) } -func (i *Ingester) verifySpindle(ctx context.Context, instance, did string) error { - spindles, err := db.GetSpindles(ctx, i.Db, - orm.FilterEq("instance", instance), - orm.FilterEq("owner", did), - ) - if err != nil { - return fmt.Errorf("look up spindle: %w", err) - } - if len(spindles) != 1 { - return fmt.Errorf("no spindle for %s by %s", instance, did) - } - if spindles[0].Verified != nil { - return nil - } - - err = retry.Do( - func() error { return serververify.RunVerification(ctx, instance, did, i.Config.Core.Dev) }, - retry.Context(ctx), - retry.Attempts(verifyAttempts), - retry.Delay(verifyMinDelay), - retry.MaxDelay(verifyMaxDelay), - retry.DelayType(retry.BackOffDelay), - retry.LastErrorOnly(true), - ) - if err != nil { - return fmt.Errorf("verify: %w", err) - } - _, err = serververify.MarkSpindleVerified(i.Db, i.Enforcer, instance, did) - return err -} - const sweepConcurrency = 4 func (i *Ingester) SweepPendingVerifications() { @@ -1334,20 +1037,6 @@ func (i *Ingester) SweepPendingVerifications() { } } - spindles, err := db.GetSpindles(i.Ctx, i.Db, orm.FilterIs("verified", nil)) - if err != nil { - l.Error("failed to list unverified spindles", "err", err) - g.Wait() - return - } - for _, s := range spindles { - g.Go(func() error { - if err := i.verifySpindle(i.Ctx, s.Instance, s.Owner.String()); err != nil { - l.Warn("verify spindle failed", "instance", s.Instance, "owner", s.Owner, "err", err) - } - return nil - }) - } g.Wait() } diff --git a/appview/oauth/handler.go b/appview/oauth/handler.go index 04f2a77f..735d9d93 100644 --- a/appview/oauth/handler.go +++ b/appview/oauth/handler.go @@ -25,7 +25,6 @@ import ( "tangled.org/core/appview/models" "tangled.org/core/consts" "tangled.org/core/idresolver" - "tangled.org/core/orm" "tangled.org/core/tid" ) @@ -119,7 +118,6 @@ func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) { o.ensureProfileRecord(sessData.AccountDID, sessData.SessionID) go o.addToDefaultKnot(sessData.AccountDID) - go o.addToDefaultSpindle(sessData.AccountDID.String()) go o.autoClaimTnglShDomain(sessData.AccountDID.String()) if !o.Config.Core.Dev { @@ -167,48 +165,6 @@ func (o *OAuth) isAccountDeactivated(sessData *oauth.ClientSessionData) bool { xrpcBody.ErrStr == "RepoDeactivated" } -func (o *OAuth) addToDefaultSpindle(did string) { - l := o.Logger.With("subject", did) - - // use the tangled.sh app password to get an accessJwt - // and create an sh.tangled.spindle.member record with that - spindleMembers, err := db.GetSpindleMembers( - o.Db, - orm.FilterEq("instance", "spindle.tangled.sh"), - orm.FilterEq("subject", did), - ) - if err != nil { - l.Error("failed to get spindle members", "err", err) - return - } - - if len(spindleMembers) != 0 { - l.Warn("already a member of the default spindle") - return - } - - l.Debug("adding to default spindle") - session, err := o.getAppPasswordSession() - if err != nil { - l.Error("failed to create session", "err", err) - return - } - - record := tangled.SpindleMember{ - LexiconTypeID: tangled.SpindleMemberNSID, - Subject: did, - Instance: consts.DefaultSpindle, - CreatedAt: time.Now().Format(time.RFC3339), - } - - if err := session.putRecord(record, tangled.SpindleMemberNSID); err != nil { - l.Error("failed to add to default spindle", "err", err) - return - } - - l.Debug("successfully added to default spindle", "did", did) -} - type onboardAction int const ( -- 2.51.2