Documentation
¶
Index ¶
- Constants
- Variables
- func AccessValue(row recordset.Row, rs recordset.Recordset, ...) (any, error)
- func AllColumnNames(rs recordset.Recordset) []string
- func ApplyFormulasToRead(data map[string]any, cols map[string]*ingitdb.ColumnDef, ...) (map[string]any, error)
- func BuildRecordset(colDef *ingitdb.CollectionDef, records []KeyedStored) recordset.Recordset
- func CollectionForKey(def *ingitdb.Definition, id string) (*ingitdb.CollectionDef, string, error)
- func NewDatabase(projectPath string, reader ingitdb.CollectionsReader, ...) (dal.DB, error)
- func NewRecordsetReader(rs recordset.Recordset) dal.RecordsetReader
- func RowData(row recordset.Row, rs recordset.Recordset, collectionID, recordKey string, ...) (map[string]any, error)
- func RowKey(row recordset.Row, rs recordset.Recordset) string
- func StoredColumnNames(rs recordset.Recordset) []string
- func ValidateDelete(def *ingitdb.Definition, parentCollection, parentKey string) error
- func ValidateWrite(def *ingitdb.Definition, operation, collectionID string, ...) error
- type CSVParseOptions
- type Database
- func (db *Database) Adapter() dal.Adapter
- func (db *Database) AlterCollection(ctx context.Context, name string, ops ...ddl.AlterOp) error
- func (db *Database) CreateCollection(_ context.Context, c dbschema.CollectionDef, opts ...ddl.Option) error
- func (db *Database) DescribeCollection(_ context.Context, ref *dal.CollectionRef) (*dbschema.CollectionDef, error)
- func (db *Database) DropCollection(_ context.Context, name string, opts ...ddl.Option) error
- func (db *Database) ExecuteQueryToRecordsReader(ctx context.Context, query dal.Query) (dal.RecordsReader, error)
- func (db *Database) ExecuteQueryToRecordsetReader(_ context.Context, _ dal.Query, _ ...recordset.Option) (dal.RecordsetReader, error)
- func (db *Database) Exists(ctx context.Context, key *dalrecord.Key) (bool, error)
- func (db *Database) Get(ctx context.Context, record dalrecord.Record) error
- func (db *Database) GetMulti(ctx context.Context, records []dalrecord.Record) error
- func (db *Database) ID() string
- func (db *Database) ListCollections(_ context.Context, _ *record.Key) ([]dal.CollectionRef, error)
- func (db *Database) ListConstraints(_ context.Context, _ *dal.CollectionRef) ([]dbschema.ConstraintDef, error)
- func (db *Database) ListIndexes(_ context.Context, _ *dal.CollectionRef) ([]dbschema.IndexDef, error)
- func (db *Database) ListReferrers(_ context.Context, _ *dal.CollectionRef) ([]dbschema.Referrer, error)
- func (db *Database) RunReadonlyTransaction(ctx context.Context, f dal.ROTxWorker, options ...dal.TransactionOption) error
- func (db *Database) RunReadwriteTransaction(ctx context.Context, f dal.RWTxWorker, options ...dal.TransactionOption) error
- func (db *Database) Schema() dal.Schema
- func (db *Database) SupportsTransactionalDDL() bool
- type DatabaseOption
- type KeyedStored
- type LockedFiles
- type OwnerPolicyController
- func (c *OwnerPolicyController) ActiveRevision(ctx context.Context) (string, error)
- func (c *OwnerPolicyController) Publish(ctx context.Context, candidate OwnerPolicyGeneration, ...) (OwnerPolicyPublication, error)
- func (c *OwnerPolicyController) Reload(ctx context.Context) (OwnerPolicySnapshot, error)
- type OwnerPolicyDocument
- type OwnerPolicyGeneration
- type OwnerPolicyPublication
- type OwnerPolicySnapshot
- type ParsedRecord
- type ProtectedAccessConfigurer
- type RootedFiles
- func (f *RootedFiles) AppendJSONL(relativePath string, value any) error
- func (f *RootedFiles) Close() error
- func (f *RootedFiles) EnsureDir(relativePath string, mode os.FileMode) error
- func (f *RootedFiles) ReadDir(relativePath string) ([]os.DirEntry, error)
- func (f *RootedFiles) ReadJSON(relativePath string, target any) error
- func (f *RootedFiles) ReadJSONL(relativePath string) ([]json.RawMessage, error)
- func (f *RootedFiles) ReadJSONLWithLimit(relativePath string, maxBytes int64) ([]json.RawMessage, error)
- func (f *RootedFiles) WithExclusiveLock(ctx context.Context, relativePath string, fn func(LockedFiles) error) error
- func (f *RootedFiles) WriteJSONAtomic(relativePath string, value any) (err error)
- func (f *RootedFiles) WriteJSONAtomicWithMode(relativePath string, value any, mode os.FileMode) error
- type RootedFilesProvider
- type RootedFilesScope
Constants ¶
const DatabaseID = "dalgo2ingitdb"
DatabaseID is the name reported by Database.ID() and used as the Adapter name.
const IDColumn = "$id"
IDColumn is the reserved recordset column that carries each record's key. It is not a declared schema column; the Starlark evaluator strips it from the stored field map so formula inputs match the eager ApplyFormulasToRead pipeline exactly. The "$id" spelling mirrors the dal pseudo-field convention and cannot collide with a real column (Starlark identifiers cannot contain "$", so no formula can reference it).
Variables ¶
var ErrCollectionPathConflict = errors.New("dalgo2ingitdb: root-collections.yaml entry conflicts with auto-registration")
ErrCollectionPathConflict is returned by CreateCollection when <projectPath>/.ingitdb/root-collections.yaml already contains an entry for the collection name with a non-default path value. Callers either remove the existing entry or pick a different collection name.
var ErrRecordAlreadyExists = dalrecord2.ErrRecordExists
ErrRecordAlreadyExists is returned (wrapped) by Insert when a record with the same key already exists. Callers detect it with errors.Is.
This is now an alias of the cross-adapter dalgo sentinel dalrecord2.ErrRecordExists (dal-go/record v0.1.3+), rather than a package-local error: dalgo's dalgotest conformance suite requires Insert-over-existing to satisfy record.IsAlreadyExists, and every adapter inventing its own duplicate-key error was exactly the fragmentation that sentinel exists to remove. Existing callers that match on errors.Is(err, ErrRecordAlreadyExists) keep working unchanged: the value this variable holds is unchanged in identity from their point of view, it's just no longer a distinct error.
Functions ¶
func AccessValue ¶
func AccessValue(row recordset.Row, rs recordset.Recordset, collectionID, recordKey, colName string, colDef *ingitdb.ColumnDef) (any, error)
AccessValue reads colName from a recordset row — the single coerce-on-access path every read consumer (select/delete/update/TUI) uses.
For a computed (formula) column the raw evaluator result is coerced to the column's declared ColumnType via coerceFormulaResult, so typed results stay identical to the eager ApplyFormulasToRead pipeline. A stored column's value (colDef nil or no Formula) is returned unchanged — the eager pipeline never coerced stored values, so neither do we.
Because computation is lazy, evaluation happens here, on access. Any evaluator or coercion error is wrapped with the collection, record key, and column, so the failure is fail-loud and names its source (matching the eager pipeline's error format).
func AllColumnNames ¶
AllColumnNames returns every column name of rs except the reserved IDColumn.
func ApplyFormulasToRead ¶
func ApplyFormulasToRead(data map[string]any, cols map[string]*ingitdb.ColumnDef, collectionID, recordKey string) (map[string]any, error)
ApplyFormulasToRead computes the value of every computed column (one with a non-empty Formula) and adds it to the returned map, coerced to the column's declared type. The stored fields in data are used as the formula's variable bindings.
When the collection has no computed columns the input map is returned unchanged (not cloned); otherwise a clone is returned with the computed values added, so the input is never mutated. Computed columns are evaluated in deterministic (sorted) order so that, when more than one formula errors, the surfaced error is reproducible.
A runtime evaluation error, or a result that cannot be coerced to the declared type, aborts with an error naming the collection, record key, and column. No partial result is returned in that case.
func BuildRecordset ¶
func BuildRecordset(colDef *ingitdb.CollectionDef, records []KeyedStored) recordset.Recordset
BuildRecordset assembles a recordset.Recordset for a collection: a reserved "$id" column carrying each record key, one ordinary column per stored (non-formula) column carrying the per-record stored value, and one recordset.NewComputedColumn per formula column bound to a Starlark-backed evaluator. Computed values are never evaluated here — they resolve lazily, at most once per row, when a consumer reads them.
func CollectionForKey ¶
func CollectionForKey(def *ingitdb.Definition, id string) (*ingitdb.CollectionDef, string, error)
CollectionForKey finds the collection and record key for a given ID string.
The id format is "{collectionID}/{recordKey}" where collection IDs use "." for namespaces. "/" is reserved for separating collection ID from record key path segments. The longest matching collection prefix wins.
func NewDatabase ¶
func NewDatabase(projectPath string, reader ingitdb.CollectionsReader, options ...DatabaseOption) (dal.DB, error)
NewDatabase constructs a Database rooted at projectPath. The reader is used to load the project Definition at the start of each transaction and inside DB-level record-access methods. Returns an error if projectPath is empty or does not exist; the constructor does NOT load any collection definitions.
func NewRecordsetReader ¶
func NewRecordsetReader(rs recordset.Recordset) dal.RecordsetReader
NewRecordsetReader returns a dal.RecordsetReader that walks the rows of rs.
func RowData ¶
func RowData(row recordset.Row, rs recordset.Recordset, collectionID, recordKey string, colDef *ingitdb.CollectionDef, names []string) (map[string]any, error)
RowData reads the named columns of a recordset row through AccessValue and returns them as a map, omitting nil values so the result matches the ragged record map the eager pipeline produced (absent fields were never keys). Only the requested columns are read, so an unreferenced computed column is never evaluated; a referenced computed column that errors surfaces fail-loud.
func RowKey ¶
RowKey returns the record key carried by a row's reserved IDColumn. The IDColumn is present in every recordset BuildRecordset produces, so the lookup cannot fail; a missing or non-string value yields the empty string.
func StoredColumnNames ¶
StoredColumnNames returns the stored (non-computed) column names of rs except the reserved IDColumn. Used by write consumers that must persist stored fields only, never computed values.
func ValidateDelete ¶
func ValidateDelete(def *ingitdb.Definition, parentCollection, parentKey string) error
ValidateDelete enforces parent-side referential integrity before a record is removed (or its key renamed, which manifests as removal of the old key): no stored or computed foreign key in any collection may still reference it.
This is the shared entry point for any DALgo driver's delete path, so enforcement is identical across drivers.
func ValidateWrite ¶
func ValidateWrite(def *ingitdb.Definition, operation, collectionID string, colDef *ingitdb.CollectionDef, recordKey string, data map[string]any) error
ValidateWrite enforces every write-time rule before a record is inserted or set, against the on-disk state described by def:
- a computed column's value must not be supplied (it is derived, not stored),
- every stored foreign key must resolve to an existing parent record, and
- every computed foreign key, evaluated from the record's stored fields, must resolve to an existing parent record.
operation labels the caller ("Insert" or "Set") for error messages. collectionID and colDef identify the collection being written; recordKey and data are the record's key and field values.
This is the shared entry point for any DALgo driver's read-write transaction, so enforcement is identical whether a record is written through the concurrent-safe driver or the filesystem driver.
Types ¶
type CSVParseOptions ¶
type CSVParseOptions struct {
// KeyColumn, if non-empty, names the column to use as the record
// key (overrides $id/id auto-resolution).
KeyColumn string
// Fields, if non-empty, replaces the header row: the first stdin
// line is treated as data and these names are used for column
// mapping.
Fields []string
}
CSVParseOptions controls CSV-specific behavior.
type Database ¶
type Database struct {
// dal.NoConcurrency makes SupportsConcurrentConnections() report false.
//
// An inGitDB database is a git working tree. We do take gofrs/flock
// advisory locks per file (shared for reads, exclusive for writes) as
// defence-in-depth, but that is NOT a basis to advertise safe concurrent
// connections, because:
// - flock is ADVISORY on Unix: it only binds processes that also call
// flock. A plain `git`, an editor, or `rm` ignores it entirely — and
// on Unix can even unlink a file out from under a held lock. It is
// mandatory only on Windows (LockFileEx), so the protection is not
// cross-platform.
// - locks are PER FILE, so a change spanning multiple files (e.g. a
// collection's definition.yaml plus root-collections.yaml, or a
// subsequent git commit) is not atomic as a unit.
// The honest cross-platform contract is therefore single-writer: callers
// MUST NOT open concurrent writing connections against the same tree.
dal.NoConcurrency
// contains filtered or unexported fields
}
Database is the dal.DB implementation for inGitDB projects on the local filesystem. It implements the schema-management capability interfaces (dbschema.SchemaReader, ddl.SchemaModifier, ddl.TransactionalDDL), the dal.DB record-access methods, and reports dal.NoConcurrency — concurrent connections are NOT advertised as safe (see the field comment for why).
Record access loads the project Definition once per transaction via the injected CollectionsReader; individual file operations take a shared (read) or exclusive (write) advisory lock on the affected file. ExecuteQueryToRecordsetReader is not yet implemented and returns dal.ErrNotSupported.
func (*Database) AlterCollection ¶
AlterCollection applies AlterOp values in order. Operations mutate an in-memory ingitdb.CollectionDef; after each op the updated definition is flushed to disk. Failure mid-sequence returns *ddl.PartialSuccessError with applied / failed / not-attempted lists.
func (*Database) CreateCollection ¶
func (db *Database) CreateCollection(_ context.Context, c dbschema.CollectionDef, opts ...ddl.Option) error
CreateCollection writes <projectPath>/<c.Name>/.collection/definition.yaml from the dbschema.CollectionDef. Validates name and field types before any filesystem write. With ddl.IfNotExists, an existing collection is a no-op; without it, an existing collection is an error.
A path-form name ("spaces/ext") declares a SUBCOLLECTION: the definition is written under the root collection's schema directory (<root>/.collection/subcollections/<sub>[/subcollections/...]/definition.yaml), where the validator-backed reader discovers it. The root collection must already exist; subcollections are not registered in root-collections.yaml.
After a root definition.yaml write succeeds, the collection is registered in <projectPath>/.ingitdb/root-collections.yaml (REQ:auto-register-in-root-collections) so the validator-backed CollectionsReader picks it up. Registry conflicts (an existing entry mapping the same name to a non-default path) return ErrCollectionPathConflict; the definition.yaml is left in place — see AC:create-collection-rejects-registry-conflict for the recovery story.
func (*Database) DescribeCollection ¶
func (db *Database) DescribeCollection(_ context.Context, ref *dal.CollectionRef) (*dbschema.CollectionDef, error)
DescribeCollection reads and parses the collection's definition.yaml under a shared lock, then maps the ingitdb columns to dbschema fields via type_mapping. PrimaryKey is synthesized as [pkFieldName] because inGitDB uses the record's filesystem key as the de-facto PK.
func (*Database) DropCollection ¶
DropCollection removes <projectPath>/<name>/ from disk. The directory must contain a .collection/definition.yaml as a safety check — this guards against accidentally deleting non-collection directories. With ddl.IfExists, a missing collection is a no-op.
func (*Database) ExecuteQueryToRecordsReader ¶
func (db *Database) ExecuteQueryToRecordsReader(ctx context.Context, query dal.Query) (dal.RecordsReader, error)
ExecuteQueryToRecordsReader runs a structured query against a single collection. See readonlyTx.ExecuteQueryToRecordsReader for supported query features.
func (*Database) ExecuteQueryToRecordsetReader ¶
func (db *Database) ExecuteQueryToRecordsetReader(_ context.Context, _ dal.Query, _ ...recordset.Option) (dal.RecordsetReader, error)
ExecuteQueryToRecordsetReader is not implemented yet; callers should use ExecuteQueryToRecordsReader instead.
func (*Database) ListCollections ¶
ListCollections walks the project directory looking for directories that contain a .collection/definition.yaml file. The parent argument is ignored (inGitDB has no catalog hierarchy). Results are sorted alphabetically by name; names use "/" as the separator for nested collection paths relative to projectPath.
func (*Database) ListConstraints ¶
func (db *Database) ListConstraints(_ context.Context, _ *dal.CollectionRef) ([]dbschema.ConstraintDef, error)
ListConstraints returns a synthesized single-element slice describing the primary-key constraint. ingitdb does not store other constraint kinds in definition.yaml. The richer PK column information lives on `DescribeCollection.PrimaryKey`; dbschema.ConstraintDef is intentionally minimal (Name + Type only).
func (*Database) ListIndexes ¶
func (db *Database) ListIndexes(_ context.Context, _ *dal.CollectionRef) ([]dbschema.IndexDef, error)
ListIndexes returns a non-nil empty slice and nil error. inGitDB has no per-collection index declarations today.
func (*Database) ListReferrers ¶
func (db *Database) ListReferrers(_ context.Context, _ *dal.CollectionRef) ([]dbschema.Referrer, error)
ListReferrers returns *dbschema.NotSupportedError — inGitDB has no structural foreign-key declarations; ColumnDef.ForeignKey is a free-text hint, not a navigable reference.
func (*Database) RunReadonlyTransaction ¶
func (db *Database) RunReadonlyTransaction(ctx context.Context, f dal.ROTxWorker, options ...dal.TransactionOption) error
RunReadonlyTransaction loads the project Definition and invokes the worker with a readonly transaction. The Definition is captured at the start of the transaction; subsequent on-disk schema changes are not observed within the transaction.
func (*Database) RunReadwriteTransaction ¶
func (db *Database) RunReadwriteTransaction(ctx context.Context, f dal.RWTxWorker, options ...dal.TransactionOption) error
RunReadwriteTransaction loads the project Definition and invokes the worker with a read-write transaction. Writes are journaled in-memory before their first filesystem mutation. If the worker or the optional Git commit fails, the touched files are restored to their exact pre-transaction state. This is deliberately a single-writer transaction: it makes a failed multi-record Synchestra state transition recoverable without pretending that a Git worktree supports concurrent multi-writer transactions.
func (*Database) Schema ¶
Schema returns nil — inGitDB does not yet expose a dal.Schema view of its collection definitions. Callers needing schema introspection should use dbschema.SchemaReader instead.
func (*Database) SupportsTransactionalDDL ¶
SupportsTransactionalDDL satisfies ddl.TransactionalDDL by reporting that this driver does NOT guarantee all-or-nothing for multi-op AlterCollection calls. A failure mid-sequence leaves earlier ops applied; the caller receives a *ddl.PartialSuccessError.
type DatabaseOption ¶ added in v0.4.0
type DatabaseOption func(*databaseOptions)
DatabaseOption configures adapter behavior selected before the database is exposed to callers.
func WithProtectedProfile ¶ added in v0.5.0
func WithProtectedProfile() DatabaseOption
WithProtectedProfile exposes the trusted coordinator factory used by a mounting database. It does not change legacy access until the factory is configured with mandatory participants.
func WithRootedFilesScopes ¶ added in v0.6.0
func WithRootedFilesScopes(scopes ...RootedFilesScope) DatabaseOption
WithRootedFilesScopes explicitly permits a legacy, unprotected server mount to issue descriptor-rooted file capabilities limited to the supplied prefixes. Protected and secured database facades deliberately do not forward this capability: their record ACLs have no path-level semantics for raw files.
func WithStoredOnlyReads ¶ added in v0.4.0
func WithStoredOnlyReads() DatabaseOption
WithStoredOnlyReads prevents evaluation and return of computed columns. It is intended for callers that apply an access-policy wrapper above this adapter and cannot authorize every dependency used by a derived value.
type KeyedStored ¶
KeyedStored pairs a record key with its locale-normalized stored fields. The stored map holds only stored (non-computed) values; computed columns are resolved lazily through the recordset, never baked in here.
type LockedFiles ¶ added in v0.6.0
type LockedFiles interface {
AppendJSONL(relativePath string, value any) error
ReadJSONL(relativePath string) ([]json.RawMessage, error)
ReadJSONLWithLimit(relativePath string, maxBytes int64) ([]json.RawMessage, error)
WriteJSONAtomic(relativePath string, value any) error
WriteJSONAtomicWithMode(relativePath string, value any, mode os.FileMode) error
ReadJSON(relativePath string, target any) error
ReadDir(relativePath string) ([]os.DirEntry, error)
}
LockedFiles is the callback-scoped view supplied by WithExclusiveLock. It may perform ordinary rooted-file operations while the store-wide lock is held, including while Close is draining that callback. The view is invalidated before WithExclusiveLock returns; retaining it beyond the callback fails closed.
type OwnerPolicyController ¶ added in v0.5.0
type OwnerPolicyController struct {
// contains filtered or unexported fields
}
OwnerPolicyController publishes immutable owner-policy generations.
func NewOwnerPolicyController ¶ added in v0.5.0
func NewOwnerPolicyController(projectPath string) (*OwnerPolicyController, error)
func (*OwnerPolicyController) ActiveRevision ¶ added in v0.5.0
func (c *OwnerPolicyController) ActiveRevision(ctx context.Context) (string, error)
func (*OwnerPolicyController) Publish ¶ added in v0.5.0
func (c *OwnerPolicyController) Publish(ctx context.Context, candidate OwnerPolicyGeneration, expectedRevision, message string) (OwnerPolicyPublication, error)
Publish writes a complete immutable generation and advances Git HEAD with an expected active-generation comparison. expectedRevision is empty only for a repository that has no active generation yet.
func (*OwnerPolicyController) Reload ¶ added in v0.5.0
func (c *OwnerPolicyController) Reload(ctx context.Context) (OwnerPolicySnapshot, error)
Reload recovers the Git-authoritative generation into the working tree and compiles one complete snapshot. It never exposes an underlying database.
type OwnerPolicyDocument ¶ added in v0.5.0
type OwnerPolicyDocument struct{ YAML []byte }
OwnerPolicyDocument is one source document in a complete owner generation.
type OwnerPolicyGeneration ¶ added in v0.5.0
type OwnerPolicyGeneration struct {
Enabled bool
Database string
Realm string
Policies []OwnerPolicyDocument
}
OwnerPolicyGeneration is the complete candidate published atomically.
type OwnerPolicyPublication ¶ added in v0.5.0
type OwnerPolicyPublication struct{ Revision, GitCommit string }
OwnerPolicyPublication is the committed result of a publication.
type OwnerPolicySnapshot ¶ added in v0.5.0
type OwnerPolicySnapshot struct {
Revision string
Config access.FilePolicyConfig
Policies []access.Policy
}
OwnerPolicySnapshot is a complete compiled generation ready for atomic installation by the database enforcement facade.
type ParsedRecord ¶
type ParsedRecord struct {
// Position is 1-based: line number for jsonl/csv, document index
// for yaml/ingr. For csv with a header row, Position 2 is the
// first data record.
Position int
// Key is the resolved record key (from $id, id, or --key-column).
Key string
// Data is the record's structured fields with the key field stripped.
Data map[string]any
}
ParsedRecord is one record extracted from a batch stream.
func ParseBatchCSV ¶
func ParseBatchCSV(r io.Reader, opts CSVParseOptions) ([]ParsedRecord, error)
ParseBatchCSV reads RFC 4180 CSV from r and returns one ParsedRecord per data row. Key resolution precedence is:
- opts.KeyColumn if set (rejected before reading rows if column missing).
- column named "$id" if present.
- column named "id" if present (auto-mapped).
- otherwise error.
When both "$id" and "id" columns exist without opts.KeyColumn, "$id" wins; "id" is kept as a data field. The resolved key column's value is stripped from Data.
If opts.Fields is non-empty, those names override the header row: the first stdin line is treated as data, and Position is 1-based against data rows. Otherwise Position is 1-based against source lines, so the header is line 1 and the first data row is line 2.
func ParseBatchINGR ¶
func ParseBatchINGR(r io.Reader) ([]ParsedRecord, error)
ParseBatchINGR reads an INGR multi-record stream from r and returns one ParsedRecord per record. The key is read from the reserved $ID column (INGR's key field; note the uppercase). $ID is stripped from the returned Data map. Position is the 1-based record index.
func ParseBatchJSONL ¶
func ParseBatchJSONL(r io.Reader) ([]ParsedRecord, error)
ParseBatchJSONL reads NDJSON from r and returns one ParsedRecord per non-blank line. Each record MUST have a top-level $id; the $id is stripped from the returned Data map. Blank lines are skipped but counted for the Position field.
func ParseBatchYAMLStream ¶
func ParseBatchYAMLStream(r io.Reader) ([]ParsedRecord, error)
ParseBatchYAMLStream reads a YAML multi-document stream from r and returns one ParsedRecord per non-nil document. Each record MUST have a top-level $id; $id is stripped from the returned Data map. Position is the 1-based document index.
type ProtectedAccessConfigurer ¶ added in v0.5.0
type ProtectedAccessConfigurer interface {
ConfigureProtectedAccess(...access.MandatoryParticipant) (dal.DB, *access.EnforcementCoordinator, error)
}
ProtectedAccessConfigurer is the trusted mount-time capability. The raw storage boundary remains private; only the fully secured facade is returned.
type RootedFiles ¶ added in v0.6.0
type RootedFiles struct {
// contains filtered or unexported fields
}
RootedFiles is a small, descriptor-rooted file capability exposed by the inGitDB DALgo adapter. It is for data formats whose persistence semantics cannot be represented by DALgo's keyed-record API, such as an append-only JSONL event stream.
Every path is relative to the authorized scope, which is itself the opened descriptor root. RootedFiles rejects an escaping path before handing it to os.Root, and os.Root keeps the opened directory stable when the original root pathname is renamed or replaced. Call Close when the capability is no longer needed.
func RootedFilesFor ¶ added in v0.6.0
func RootedFilesFor(ctx context.Context, db dal.DB, scope RootedFilesScope) (*RootedFiles, error)
RootedFilesFor opens a scoped rooted-file capability from a DALgo database that explicitly advertises RootedFilesProvider. It deliberately uses a direct assertion rather than dal.As so a secured or protected wrapper cannot unwrap and bypass its ACL boundary.
func (*RootedFiles) AppendJSONL ¶ added in v0.6.0
func (f *RootedFiles) AppendJSONL(relativePath string, value any) error
AppendJSONL serializes value as one JSON object and durably appends it to relativePath. Existing bytes are never reserialized or rewritten. On platforms with file locking, cooperating RootedFiles readers and writers are serialized around the complete line.
func (*RootedFiles) Close ¶ added in v0.6.0
func (f *RootedFiles) Close() error
Close releases the opened root directory handle.
func (*RootedFiles) EnsureDir ¶ added in v0.6.0
func (f *RootedFiles) EnsureDir(relativePath string, mode os.FileMode) error
EnsureDir creates one scoped top-level directory with mode, or sets the requested mode on that directory if it already exists. The one-segment contract avoids a multi-component pathname acquisition race. A new link and its parent are synced so private store metadata can survive a crash without a raw filesystem handle. mode may contain Unix permission bits only and must permit owner read and traversal.
func (*RootedFiles) ReadDir ¶ added in v0.6.0
func (f *RootedFiles) ReadDir(relativePath string) ([]os.DirEntry, error)
ReadDir returns the entries directly below a scoped relative directory.
func (*RootedFiles) ReadJSON ¶ added in v0.6.0
func (f *RootedFiles) ReadJSON(relativePath string, target any) error
ReadJSON decodes the JSON document at relativePath into target.
func (*RootedFiles) ReadJSONL ¶ added in v0.6.0
func (f *RootedFiles) ReadJSONL(relativePath string) ([]json.RawMessage, error)
ReadJSONL returns each non-blank JSON object from relativePath in file order. The returned values are independent copies of the on-disk lines.
func (*RootedFiles) ReadJSONLWithLimit ¶ added in v0.6.0
func (f *RootedFiles) ReadJSONLWithLimit(relativePath string, maxBytes int64) ([]json.RawMessage, error)
ReadJSONLWithLimit reads and decodes a JSONL stream whose returned content buffer capacity never exceeds maxBytes, without preallocating a huge maxBytes buffer for a tiny stream. maxBytes must be positive. Like ReadJSONL, this public read is non-mutating and refuses an interrupted final line.
func (*RootedFiles) WithExclusiveLock ¶ added in v0.6.0
func (f *RootedFiles) WithExclusiveLock(ctx context.Context, relativePath string, fn func(LockedFiles) error) error
WithExclusiveLock runs fn while holding an advisory exclusive lock on a scoped relative file. Its operation lease remains live across fn, so Close waits for the callback. fn receives the only callback-scoped view that may operate while Close drains; the view is invalid when fn returns. The lock remains held until fn returns or ctx is cancelled while waiting to acquire it.
func (*RootedFiles) WriteJSONAtomic ¶ added in v0.6.0
func (f *RootedFiles) WriteJSONAtomic(relativePath string, value any) (err error)
WriteJSONAtomic serializes value and atomically publishes it at relativePath. It writes and syncs a private sibling temporary file before rename, then syncs the containing directory so a crash cannot expose a partially-written projection. It does not choose a winner between concurrent projection writers; callers that need a sequence contract must serialize at their mutation boundary.
func (*RootedFiles) WriteJSONAtomicWithMode ¶ added in v0.6.0
func (f *RootedFiles) WriteJSONAtomicWithMode(relativePath string, value any, mode os.FileMode) error
WriteJSONAtomicWithMode serializes value and atomically publishes it at relativePath with the requested Unix permission bits. It is intended for callers whose records have a stricter storage classification than the default public projection mode used by WriteJSONAtomic.
type RootedFilesProvider ¶ added in v0.6.0
type RootedFilesProvider interface {
OpenRootedFiles(ctx context.Context, scope RootedFilesScope) (*RootedFiles, error)
}
RootedFilesProvider is an optional DALgo capability intentionally exposed only by an unprotected server mount configured with WithRootedFilesScopes. Protected and secured facades do not forward it because their record ACLs do not authorize arbitrary raw-file paths.
type RootedFilesScope ¶ added in v0.6.0
type RootedFilesScope struct {
Prefix string
}
RootedFilesScope is an explicitly authorized, top-level directory for raw inGitDB files. The MVP intentionally supports exactly one clean path segment (for example, "incidents"), configured by a trusted server mount rather than accepted from an untrusted request.
Source Files
¶
- access_generation.go
- access_manifest.go
- accessor.go
- batch_parsers.go
- collection.go
- computed_columns.go
- database.go
- filelock.go
- filelock_path_other.go
- foreign_keys.go
- formula.go
- git_commit.go
- protected.go
- query.go
- record_io.go
- recordset.go
- registry.go
- rooted_files.go
- rooted_files_unix.go
- schema_modifier.go
- schema_reader.go
- scoped_collection.go
- seams.go
- slice_records_reader.go
- tx_readonly.go
- tx_readwrite.go
- type_mapping.go
- write_validation.go