package console import ( "context" "errors" "github.com/carlosframework/platform/internal/hostops" "github.com/carlosframework/platform/internal/release" ) // withAutoAppSQL is used by the explicit generated adapters on existing Store // mutation methods. Direct db writes remain refused. A future Store method // receives no adapter until its scope and route fixture are reviewed. func (s *Store) withAutoAppSQL(ctx context.Context, accountID int64, app, action string, call func(*Store) error) error { if app == "" || s.gate == nil || s.bound != nil { return call(s) } if s.outerInsideView() { return errOuterStoreInView } if s.claimSQLAdmit == nil || s.claimBucket == nil { return hostops.ErrContract } acct, err := s.AccountByID(accountID) if err != nil { return err } if acct == nil { return hostops.ErrIdentity } var sqlErr error err = s.claimSQLAdmit(ctx, acct.Sqid, app, action, func(pctx context.Context) error { a, err := hostops.ReadCanonicalAdmission(pctx, s.claimBucket, acct.Sqid, app) if err != nil { return err } scope := claimSQLScope{AccountID: accountID, App: app, AppID: a.Value.AppID, Mode: claimModeEffect} sqlErr = s.WithAppMutation(pctx, []sqlGrant{permitGrant(pctx, s.claimBucket, acct.Sqid, scope)}, call) // The bound view has released its connection before this returns. // Any unproven failure remains uncertain until local SQL recovery fences it. return sqlErr }) // The admission door normally returns the callback's error itself. if err != nil && errors.Is(err, sqlErr) { return err } return errors.Join(sqlErr, err) } func (s *Store) bindClaimSQLMutations(bucket release.Store) error { if s.gate == nil { return hostops.ErrContract } runner, ok := bucket.(hostops.SQLIngestRunner) if !ok { return hostops.ErrContract } s.claimBucket = bucket database, err := s.sqlDatabaseID() if err != nil { return err } s.claimSQLAdmit = func(ctx context.Context, account, app, action string, fn func(context.Context) error) error { return runner.RunSQLIngest(ctx, account, app, action, database, fn) } return nil }