document

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package document is wowapi's document / file framework: modules register document CLASSES (the policy envelope for a kind of file — allowed MIME types, a size ceiling, a default sensitivity, and an optional retention window); the service manages metadata rows, presigned upload sessions, immutable versioned file pointers, authorized presigned downloads, explicit access grants, and a retention sweep. Blob bytes never transit the API process — they flow client ↔ object store through short-lived presigned URLs (kernel/storage). Contract: blueprint 07 §4.

Index

Constants

View Source
const (
	PermRead = "kernel.document.read"
	// PermWrite is the authz permission for mutating a document (managing grants,
	// adding versions). "update" is the closed-set verb for write access; the
	// grant table's own access column still uses the literal "write".
	PermWrite = "kernel.document.update"
)

Permissions the download gate evaluates when an authz Evaluator is wired. The consumer registers them (kernel.document.read/write) at boot; the framework wiring does so by default.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessEvent

type AccessEvent struct {
	DocumentID  string
	VersionNo   int
	Sensitivity Sensitivity
	ActorID     string
}

AccessEvent is passed to OnDocumentAccess hooks after authorization succeeds and before the presigned GET is minted. A hook returning an error denies the download. The watermark slot lives here.

type AccessHook

type AccessHook func(context.Context, AccessEvent) error

UploadHook runs on confirm; AccessHook runs on download.

type Class

type Class struct {
	Key                string
	Module             string
	DefaultSensitivity Sensitivity   // applied when Create omits sensitivity
	MaxBytes           int64         // 0 = no ceiling
	AllowedMIME        []string      // empty = any sniffed type accepted
	Retention          time.Duration // 0 = keep forever; else retention_until = created_at + Retention
}

Class is a registered document class: the policy envelope a module declares for one kind of document.

type ConfirmInput

type ConfirmInput struct {
	DocumentID       uuid.UUID
	VersionNo        int
	StorageKey       string
	DeclaredSize     int64
	DeclaredChecksum string
	DeclaredMIME     string
}

ConfirmInput finalizes an uploaded version. Declared size/checksum/MIME are verified against the stored object before the immutable row is written.

type CreateInput

type CreateInput struct {
	Class       string
	Resource    resource.Ref
	Title       string
	Sensitivity Sensitivity // "" → the class default
}

CreateInput describes a new document's metadata. Resource is an optional anchor.

type Download

type Download struct {
	VersionNo int
	MIME      string
	URL       storage.PresignedURL
}

Download is an authorized, time-boxed download of one version.

type DownloadInput

type DownloadInput struct {
	DocumentID uuid.UUID
	VersionNo  int
}

DownloadInput selects a version to download; VersionNo 0 → latest active.

type GrantInput

type GrantInput struct {
	DocumentID  uuid.UUID
	GranteeKind string // capacity | role | relationship
	GranteeRef  string
	Access      string // read | write
	ValidTo     *time.Time
}

GrantInput adds an explicit access grant beyond policy.

type Hooks

type Hooks struct {
	// contains filtered or unexported fields
}

Hooks is the registry of upload/access hooks a module wires at boot.

func NewHooks

func NewHooks() *Hooks

NewHooks returns an empty hook set.

func (*Hooks) OnDocumentAccess

func (h *Hooks) OnDocumentAccess(fn AccessHook)

OnDocumentAccess registers a download-time hook.

func (*Hooks) OnFileUpload

func (h *Hooks) OnFileUpload(fn UploadHook)

OnFileUpload registers a confirm-time hook.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry collects document classes during module registration.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty class registry.

func (*Registry) Err

func (r *Registry) Err() error

Err returns accumulated registration errors joined, or nil.

func (*Registry) Get

func (r *Registry) Get(key string) (Class, bool)

Get returns the registered class.

func (*Registry) Keys

func (r *Registry) Keys() []string

Keys returns registered class keys, sorted.

func (*Registry) Register

func (r *Registry) Register(module string, c Class)

Register adds a document class. Malformed keys, a module-prefix mismatch, an invalid default sensitivity, or a duplicate are recorded and surfaced by Err().

type Sensitivity

type Sensitivity string

Sensitivity ranks how protected a document is. Ordered; the download scan-gate blocks pending scans at confidential and above.

const (
	SensitivityPublic       Sensitivity = "public"
	SensitivityInternal     Sensitivity = "internal"
	SensitivityConfidential Sensitivity = "confidential"
	SensitivityRestricted   Sensitivity = "restricted"
)

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the document framework. Metadata mutations run inside the caller's tenant transaction (so a document commits with its business write); scan-status and retention voiding run on a platform-privileged tenant-bound manager because document_versions is append-only to the module role.

func New

func New(reg *Registry, store storage.Adapter, ev authz.Evaluator, ob outbox.Writer, hooks *Hooks, idgen model.IDGen) *Service

New wires the service. registry/store/outbox/idgen are required; authz and hooks are optional.

func (*Service) ConfirmUpload

func (s *Service) ConfirmUpload(ctx context.Context, db database.TenantDB, in ConfirmInput) (uuid.UUID, error)

ConfirmUpload verifies the uploaded bytes (size, checksum, MIME sniff, class limits), runs OnFileUpload hooks, and writes the immutable version row.

func (*Service) Create

func (s *Service) Create(ctx context.Context, db database.TenantDB, in CreateInput) (uuid.UUID, error)

Create writes a document metadata row and returns its id.

func (*Service) Download

func (s *Service) Download(ctx context.Context, db database.TenantDB, actor authz.Actor, in DownloadInput) (Download, error)

Download authorizes and returns a short-lived presigned GET for a version.

func (*Service) Grant

func (s *Service) Grant(ctx context.Context, db database.TenantDB, in GrantInput) (uuid.UUID, error)

Grant records an explicit access grant. The caller must be able to write the document (owner, a write grant, or a policy write-allow).

func (*Service) InitiateUpload

func (s *Service) InitiateUpload(ctx context.Context, db database.TenantDB, docID uuid.UUID) (UploadSession, error)

InitiateUpload reserves the next version number and returns a presigned PUT for a tenant-prefixed key. The version row is written only on ConfirmUpload.

func (*Service) Revoke

func (s *Service) Revoke(ctx context.Context, db database.TenantDB, grantID uuid.UUID) error

Revoke closes a grant's validity window (soft revoke; grants are auditable). The caller must be able to write the grant's document — the same gate as Grant (SEC-43); the restrictive grant-ownership RLS policy is the DB-level backstop.

func (*Service) SweepRetention

func (s *Service) SweepRetention(ctx context.Context, plat database.TxManager, tenantID uuid.UUID, at time.Time) (int, error)

SweepRetention voids every active version of every document whose retention has lapsed (legal-hold documents are skipped) and tombstones the rows, then deletes the blobs. Runs as app_platform, tenant-bound. The row voiding commits FIRST; blob deletion happens only AFTER the commit succeeds (SEC-48) — so a mid-sweep failure never leaves an active row pointing at a deleted blob. A blob-delete failure after commit merely orphans the blob (swept by a future storage GC). Idempotent: a re-run over an already-swept tenant voids nothing. Returns the number of versions voided.

func (*Service) UpdateScanStatus

func (s *Service) UpdateScanStatus(ctx context.Context, plat database.TxManager, tenantID, versionID uuid.UUID, result string) error

UpdateScanStatus records the result of an async malware scan. Runs as app_platform (document_versions is append-only to the module role); a scan may only leave the pending state once.

type UploadEvent

type UploadEvent struct {
	DocumentID  string
	Class       string
	VersionNo   int
	StorageKey  string
	MIME        string
	SizeBytes   int64
	Sensitivity Sensitivity
}

UploadEvent is passed to OnFileUpload hooks after a version's bytes are verified but before the version row is committed. A hook returning an error aborts the confirm (the version is not written). The canonical hook enqueues an async malware scan; the version lands scan_status=pending and downloads of confidential+ documents block until the scan clears it.

type UploadHook

type UploadHook func(context.Context, UploadEvent) error

UploadHook runs on confirm; AccessHook runs on download.

type UploadSession

type UploadSession struct {
	DocumentID uuid.UUID
	VersionNo  int
	StorageKey string
	Upload     storage.PresignedURL
}

UploadSession is what a client needs to PUT a version's bytes.

Jump to

Keyboard shortcuts

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