Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Storage Package

import "github.com/sw33tLie/bbscope/v2/pkg/storage"

The storage package provides the PostgreSQL persistence layer. It handles schema creation, scope upserts with change detection, querying, and searching.

Opening a connection

db, err := storage.Open("postgres://user:pass@localhost/bbscope?sslmode=disable")
if err != nil {
    log.Fatal(err)
}
defer db.Close()

Open automatically creates all tables and indexes if they don’t exist.

Key types

TargetItem

Input type for building entries:

type TargetItem struct {
    URI         string
    Category    string
    Description string
    InScope     bool
    IsBBP       bool
    Variants    []TargetVariant  // AI-normalized variants
}

Change

Represents a detected scope change:

type Change struct {
    OccurredAt         time.Time
    ProgramURL         string
    Platform           string
    Handle             string
    TargetNormalized   string
    TargetRaw          string
    TargetAINormalized string
    Category           string
    InScope            bool
    IsBBP              bool
    ChangeType         string  // "added", "removed", "updated"
}

Core operations

Upserting scope data

// Build entries from target items
entries, err := storage.BuildEntries(programURL, platform, handle, items)

// Upsert and get changes
changes, err := db.UpsertProgramEntries(ctx, programURL, platform, handle, entries)

UpsertProgramEntries compares the new entries against what’s in the database and returns the diff as []Change. It also updates timestamps and handles additions/removals/updates atomically.

Syncing removed programs

changes, err := db.SyncPlatformPrograms(ctx, "h1", polledProgramURLs)

Marks programs not in polledProgramURLs as disabled and returns removal changes.

Logging changes

err := db.LogChanges(ctx, changes)

Persists changes to the scope_changes table for later querying.

Querying

// List entries with filters
entries, err := db.ListEntries(ctx, storage.ListOptions{
    Platform: "h1",
    InScope:  true,
})

// Full-text search
results, err := db.SearchTargets(ctx, "example.com")

// Recent changes (limit, since, until — use zero time for no filter)
changes, err := db.ListRecentChanges(ctx, 50, time.Time{}, time.Time{})

// Statistics
stats, err := db.GetStats(ctx)

Program management

// Get program count
count, err := db.GetActiveProgramCount(ctx, "h1")

// Get ignored programs
ignored, err := db.GetIgnoredPrograms(ctx, "h1")

// AI enhancements cache
enhancements, err := db.ListAIEnhancements(ctx, programURL)

Normalization helpers

// Normalize a target string (lowercase, strip ports, etc.)
normalized := storage.NormalizeTarget(raw, category)

// Build cache key for AI enhancement lookups
key := storage.BuildTargetCategoryKey(target, category)

// Aggressive transform: extract root domain via publicsuffix
root := storage.AggressiveTransform(target)