blindindexstore

package module
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: GPL-3.0 Imports: 17 Imported by: 0

README

Blind Index Store Open in Gitpod

Tests Status Go Report Card PkgGoDev

Blind Index Store helps you create and manage blind index database tables so you can search encrypted or tokenized data without exposing the original plaintext. It ships with reference transformers, query builders, and a high-level API for CRUD operations over blind-indexed values.

Features

  • Turnkey store Instantiates with NewStore() and optional auto-migration support.
  • Flexible transformers Implements TransformerInterface so you can plug in hashing, reversible, or custom blinding strategies.
  • Rich querying Supports equals, contains, starts-with, and ends-with search semantics (subject to transformer capabilities).
  • Soft deletes Keeps records retrievable when you include soft-deleted values in queries.
  • Test coverage Includes unit tests that exercise the store, query builder, and sample transformers.

Installation

  • Go version Requires Go 1.24+ (see go.mod).
  • Module
go get github.com/dracory/blindindexstore

Quick start

package main

import (
    "database/sql"
    "log"

    blindindexstore "github.com/dracory/blindindexstore"
    _ "modernc.org/sqlite"
)

func main() {
    db, err := sql.Open("sqlite", "file:blindindex.db?cache=shared&mode=rwc")
    if err != nil {
        log.Fatal(err)
    }

    store, err := blindindexstore.NewStore(blindindexstore.NewStoreOptions{
        DB:                 db,
        TableName:          "blindindex_emails",
        AutomigrateEnabled: true,
        Transformer:        &blindindexstore.Sha256Transformer{},
    })
    if err != nil {
        log.Fatal(err)
    }

    value := blindindexstore.NewSearchValue().
        SetSourceReferenceID("USER01").
        SetSearchValue("user01@test.com")

    if err := store.SearchValueCreate(value); err != nil {
        log.Fatal(err)
    }

    refs, err := store.Search("user01@test.com", blindindexstore.SEARCH_TYPE_EQUALS)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Refs found: %v", refs)
}

Store configuration

  • NewStoreOptions

    • TableName Name of the table that stores blind index entries. Required.
    • DB Any *sql.DB connection. Required.
    • DbDriverName Optional override. Defaults to sb.DatabaseDriverName(DB).
    • AutomigrateEnabled Automatically creates the table using sqlTableCreate().
    • DebugEnabled Enables SQL logging.
    • Transformer Any TransformerInterface. Required.
  • Automigration Call NewStore with AutomigrateEnabled: true or invoke store.AutoMigrate() manually.

  • Debug logging Toggle at runtime with store.EnableDebug(true).

Working with search values

  • Create Use NewSearchValue() to build a value, then store.SearchValueCreate().
  • Update Mutate fields and call store.SearchValueUpdate(); the transformer re-runs when the search value changes.
  • List Build a query with NewSearchValueQuery() and pass it to store.SearchValueList().
  • Soft delete Use store.SearchValueSoftDelete() or SearchValueSoftDeleteByID() and include soft-deleted rows via SetWithSoftDeleted(true).
  • Hard delete Call store.SearchValueDelete() or SearchValueDeleteByID().

SearchValue instances carry metadata columns (created_at, updated_at, soft_deleted_at, metas) and helper methods for managing JSON-encoded metas.

Searching

  • Search API store.Search(searchTerm, searchType) returns matching source reference IDs.
  • Search types
    • SEARCH_TYPE_EQUALS
    • SEARCH_TYPE_CONTAINS
    • SEARCH_TYPE_STARTS_WITH
    • SEARCH_TYPE_ENDS_WITH
  • Transformer awareness The transformer decides what search types are meaningful. Deterministic hashes typically support equality only; reversible or passthrough transformers can support partial matches.

To build more complex queries (limits, ordering, soft delete filters), compose a SearchValueQuery and pass it to store.SearchValueList().

Custom transformers

  • Interface Implement a single method: Transform(string) string.
  • Examples included NoChangeTransformer, Rot13Transformer, Sha256Transformer, UniTransformer in transformer_interface.go.
  • Recommendations
    • Use cryptographically strong, deterministic functions (for equality searches).
    • If supporting partial searches, document the associated trade-offs clearly.
type BcryptPrefixTransformer struct{}

func (t *BcryptPrefixTransformer) Transform(v string) string {
    hashed := bcrypt.Sum([]byte(v))
    return hex.EncodeToString(hashed[:8])
}

Plug your transformer into NewStoreOptions{ Transformer: &BcryptPrefixTransformer{} }.

Testing

  • Run tests
go test ./...

The suite exercises querying behaviour, transformers, soft deletes, and truncate helpers against an in-memory SQLite database (modernc.org/sqlite).

License

  • Open-source Licensed under the GNU General Public License v3. See LICENSE.
  • Commercial Contact lesichkov.co.uk/contact for commercial licensing options.

Documentation

Index

Constants

View Source
const COLUMN_CREATED_AT = "created_at"
View Source
const COLUMN_ID = "id"
View Source
const COLUMN_METAS = "metas"
View Source
const COLUMN_SEARCH_VALUE = "search_value"
View Source
const COLUMN_SOFT_DELETED_AT = "soft_deleted_at"
View Source
const COLUMN_SOURCE_REFERENCE_ID = "source_reference_id"
View Source
const COLUMN_UPDATED_AT = "updated_at"
View Source
const SEARCH_TYPE_CONTAINS = "contains"
View Source
const SEARCH_TYPE_ENDS_WITH = "ends_with"
View Source
const SEARCH_TYPE_EQUALS = "equals"
View Source
const SEARCH_TYPE_STARTS_WITH = "starts_with"

Variables

This section is empty.

Functions

This section is empty.

Types

type NewStoreOptions

type NewStoreOptions struct {
	TableName          string
	DB                 *sql.DB
	DbDriverName       string
	AutomigrateEnabled bool
	DebugEnabled       bool
	Transformer        TransformerInterface
}

NewStoreOptions define the options for creating a new session store

type NoChangeTransformer

type NoChangeTransformer struct{}

Example transformer not doing anything (do not use in production)

func (*NoChangeTransformer) Transform

func (t *NoChangeTransformer) Transform(v string) string

type Rot13Transformer

type Rot13Transformer struct{}

Example transformer using ROT13 (do not use in production)

func (*Rot13Transformer) Transform

func (t *Rot13Transformer) Transform(v string) string

type SearchValueInterface added in v1.6.0

type SearchValueInterface interface {
	Data() map[string]string
	DataChanged() map[string]string
	MarkAsNotDirty()

	CreatedAt() string
	SetCreatedAt(createdAt string) SearchValueInterface
	CreatedAtCarbon() *carbon.Carbon

	SearchValue() string
	SetSearchValue(value string) SearchValueInterface

	SourceReferenceID() string
	SetSourceReferenceID(sourceReferenceID string) SearchValueInterface

	ID() string
	SetID(id string) SearchValueInterface

	Metas() (map[string]string, error)
	SetMetas(data map[string]string) (SearchValueInterface, error)

	HasMeta(key string) (bool, error)
	Meta(key string) (string, error)
	SetMeta(key string, value string) (SearchValueInterface, error)
	DeleteMeta(key string) (SearchValueInterface, error)

	SoftDeletedAt() string
	SetSoftDeletedAt(softDeletedAt string) SearchValueInterface
	SoftDeletedAtCarbon() *carbon.Carbon

	UpdatedAt() string
	SetUpdatedAt(updatedAt string) SearchValueInterface
	UpdatedAtCarbon() *carbon.Carbon
}

SearchValueInterface defines the methods for a SearchValue entity This interface can be implemented by any SearchValue struct for flexibility and testability.

func NewSearchValue

func NewSearchValue() SearchValueInterface

func NewSearchValueFromExistingData

func NewSearchValueFromExistingData(data map[string]string) SearchValueInterface

type SearchValueQueryInterface added in v1.6.0

type SearchValueQueryInterface interface {
	ToSelectDataset(store StoreInterface) (*goqu.SelectDataset, []any, error)
	Validate() error

	ID() string
	HasID() bool
	SetID(id string) SearchValueQueryInterface

	IDIn() []string
	HasIDIn() bool
	SetIDIn(idIn []string) SearchValueQueryInterface

	SourceReferenceID() string
	HasSourceReferenceID() bool
	SetSourceReferenceID(sourceReferenceID string) SearchValueQueryInterface

	SearchValue() string
	HasSearchValue() bool
	SetSearchValue(searchValue string) SearchValueQueryInterface

	SearchType() string
	HasSearchType() bool
	SetSearchType(searchType string) SearchValueQueryInterface

	Offset() int
	HasOffset() bool
	SetOffset(offset int) SearchValueQueryInterface

	Limit() int
	HasLimit() bool
	SetLimit(limit int) SearchValueQueryInterface

	OrderBy() string
	HasOrderBy() bool
	SetOrderBy(orderBy string) SearchValueQueryInterface

	OrderDirection() string
	HasOrderDirection() bool
	SetOrderDirection(orderByDirection string) SearchValueQueryInterface

	CountOnly() bool
	HasCountOnly() bool
	SetCountOnly(countOnly bool) SearchValueQueryInterface

	WithSoftDeleted() bool
	HasWithSoftDeleted() bool
	SetWithSoftDeleted(withSoftDeleted bool) SearchValueQueryInterface

	Columns() []any
	HasColumns() bool
	SetColumns(columns []any) SearchValueQueryInterface
}

func NewSearchValueQuery added in v1.6.0

func NewSearchValueQuery() SearchValueQueryInterface

func SearchValueQuery added in v1.6.0

func SearchValueQuery() SearchValueQueryInterface

type Sha256Transformer

type Sha256Transformer struct{}

Example transformer using SHA256

func (*Sha256Transformer) Transform

func (t *Sha256Transformer) Transform(v string) string

type StoreInterface

type StoreInterface interface {
	AutoMigrate() error

	Search(ctx context.Context, needle, searchType string) (refIDs []string, err error)
	SearchValueCreate(ctx context.Context, value SearchValueInterface) error
	SearchValueDelete(ctx context.Context, value SearchValueInterface) error
	SearchValueDeleteByID(ctx context.Context, valueID string) error
	SearchValueFindByID(ctx context.Context, id string) (SearchValueInterface, error)
	SearchValueFindBySourceReferenceID(ctx context.Context, sourceReferenceID string) (SearchValueInterface, error)
	SearchValueList(ctx context.Context, query SearchValueQueryInterface) ([]SearchValueInterface, error)
	SearchValueSoftDelete(ctx context.Context, discount SearchValueInterface) error
	SearchValueSoftDeleteByID(ctx context.Context, discountID string) error
	SearchValueUpdate(ctx context.Context, value SearchValueInterface) error
	Truncate(ctx context.Context) error

	// IsAutomigrateEnabled returns whether automigrate is enabled
	IsAutomigrateEnabled() bool
}

func NewStore

func NewStore(opts NewStoreOptions) (StoreInterface, error)

NewStore creates a new entity store

type TransformerInterface

type TransformerInterface interface {
	Transform(string) string
}

type UniTransformer

type UniTransformer struct{}

Example custom transformer (do not use in production)

func (*UniTransformer) Transform

func (t *UniTransformer) Transform(v string) string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL