cortex

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	FederationModeSync      = "sync"      // bidirectional: pull from peers + serve events
	FederationModePublish   = "publish"   // outbound only: serve events, never pull
	FederationModeSubscribe = "subscribe" // inbound only: pull from peers, refuse to serve
)

Federation mode constants.

View Source
const (
	PeerModeSync   = "sync"   // actively pull from this peer
	PeerModePaused = "paused" // configured but skipped by the syncer
)

Peer mode constants.

View Source
const AccessKeyEnvVar = "NOEMA_MCP_KEY"

AccessKeyEnvVar is the environment variable that overrides cortex.md's access.shared_key_file. When set to a non-empty, non- whitespace value it is used as the MCP shared key, and any configured file path is recorded so the caller can warn about the override.

View Source
const ManifestVersion = 2

ManifestVersion is the current cortex.md schema version. Cortexes written at this version carry an `id` field; cortexes at any earlier version must be migrated via `noema migrate cortex-id` before federation will accept them.

Variables

View Source
var ErrSourceLocked = errors.New("trace is source-locked")

ErrSourceLocked is returned when a mutation is attempted on a source-locked trace from a foreign origin.

Functions

func KeyFingerprint added in v0.3.0

func KeyFingerprint(key string) string

KeyFingerprint returns a non-secret SHA-256 fingerprint of an MCP shared key, formatted SSH-style as SHA256:<pair>:<pair>:... Safe to log, display in federation_status, and read aloud over an out-of-band channel when confirming a pairing.

func WriteManifest added in v0.3.0

func WriteManifest(dir string, m Manifest) error

WriteManifest writes the manifest back to cortex.md in the given directory.

Types

type AccessConfig added in v0.3.0

type AccessConfig struct {
	// SharedKeyFile is a path to a sidecar file whose first non-empty
	// line is the shared bearer token. Relative paths are resolved
	// against the cortex directory. The manifest itself never holds the
	// secret — only a pointer to where it lives.
	SharedKeyFile string `yaml:"shared_key_file,omitempty"`
}

AccessConfig holds MCP endpoint authentication settings for cortex.md. When SharedKeyFile is set, the HTTP MCP endpoint runs in shared-key mode and every incoming request must carry a matching Authorization bearer header. See docs/design/mcp-auth-plan.md for the full design.

type AccessKey added in v0.3.0

type AccessKey struct {
	// Value is the raw bearer token. It must never be logged, written to
	// the event log, serialised to MCP responses, or echoed in error
	// messages. Only the Fingerprint is safe to surface.
	Value string

	// Source is "env" (NOEMA_MCP_KEY), "file" (read from disk), or ""
	// (open mode).
	Source string

	// Path is the absolute file path the key was read from when
	// Source == "file", or the configured-but-overridden file path when
	// Source == "env" and the manifest also declared a shared_key_file.
	// Empty when neither applies.
	Path string

	// Fingerprint is a non-secret SHA-256 digest of Value, formatted
	// SSH-style (e.g. SHA256:a3:f1:...:c2). Safe to log and display.
	Fingerprint string
}

AccessKey is the resolved shared key for the HTTP MCP endpoint, along with metadata about where it came from and a non-secret fingerprint. The zero value represents open mode (no authentication).

func LoadAccessKey added in v0.3.0

func LoadAccessKey(cortexDir string, cfg *AccessConfig) (AccessKey, error)

LoadAccessKey resolves the active MCP shared key for a cortex.

Resolution order (highest priority first):

  1. NOEMA_MCP_KEY — if set to a non-empty value, wins. The configured file path is still recorded in AccessKey.Path so the caller can log that the env var overrode it.
  2. cfg.SharedKeyFile — read relative to cortexDir unless already absolute. The file is validated for permissions, size, and format (see loadKeyFile).
  3. Open mode — returns the zero AccessKey with a nil error.

Errors are returned when the env var is set to only whitespace, when a configured file cannot be read, when permissions are looser than 0600, when the file exceeds 4 KiB, when it is empty or whitespace only, or when it contains two or more non-empty lines.

func (AccessKey) EnvOverride added in v0.3.0

func (k AccessKey) EnvOverride() bool

EnvOverride reports whether NOEMA_MCP_KEY took precedence over a configured access.shared_key_file. Callers use this to emit the one-line warning on startup.

func (AccessKey) Keyed added in v0.3.0

func (k AccessKey) Keyed() bool

Keyed reports whether shared-key mode is active.

type BackfillResult added in v0.3.0

type BackfillResult struct {
	BackfilledIDs []string // active traces that received a synthetic create event
	SkippedIDs    []string // traces with no create event but currently archived/trashed
}

BackfillResult summarises a `noema events backfill` operation. The slices hold trace IDs (not row counts) so the caller can render them line-by-line for the operator's audit trail.

type Cortex

type Cortex struct {
	ID   string // ULID, stable across renames; the federation identity key
	Name string // human-readable display label
	Dir  string
	DB   *db.DB
	// contains filtered or unexported fields
}

func Open

func Open(name, dir string) (*Cortex, error)

Open opens an existing Cortex by directory path. It ensures required subdirectories exist and auto-purges expired trash.

func (*Cortex) Add

func (c *Cortex) Add(t *trace.Trace) error

Add writes a new Trace to disk and inserts it into the DB.

func (*Cortex) Archive

func (c *Cortex) Archive(id string) error

func (*Cortex) ArchiveDir

func (c *Cortex) ArchiveDir() string

func (*Cortex) BackfillCreateEvents added in v0.3.0

func (c *Cortex) BackfillCreateEvents(dryRun bool) (BackfillResult, error)

BackfillCreateEvents emits synthetic `create` events for any active trace that lacks one in the event log. This folds traces that pre-date the event log — or that landed via `noema sync`, which intentionally emits no events because it is reconciliation, not a semantic mutation — back into the federated history so peers can replay them.

Each backfilled event uses a fresh ULID, the local cortex_id and origin, the current wall-clock time as the event timestamp, and a JSON snapshot of the trace's current frontmatter + body. The trace's own `created` field (in the markdown frontmatter and the DB row) is left untouched, so the audit trail still surfaces "this happened on <real date>" — the event timestamp only records when the backfill ran. Using wall-clock time keeps per-cortex ULID monotonicity and avoids the event log lying about when the event was actually appended.

Archived and trashed traces are skipped: emitting only a `create` event for them would leave federation diverged (peers would materialise the trace as active and never see the archive/trash). Recover or unarchive the trace first if it needs to federate.

If dryRun is true, no events are written and the vector clock is not touched, but the returned result still lists every trace that would have been backfilled or skipped — so operators can preview before committing.

The iteration is idempotent: traces that already have a create event in the log (whether locally emitted or replayed from a peer) are not in the candidate set, so running this twice is a no-op on the second pass.

func (*Cortex) CheckSourceLock added in v0.5.0

func (c *Cortex) CheckSourceLock(id string) error

CheckSourceLock returns ErrSourceLocked if the trace is source-locked by a foreign origin. The check is skipped when forceSourceLock is set.

func (*Cortex) Close

func (c *Cortex) Close() error

func (*Cortex) DerivedBy added in v0.3.0

func (c *Cortex) DerivedBy(id string) ([]string, error)

DerivedBy returns all trace IDs that list the given trace as a source.

func (*Cortex) DivergenceCount added in v0.3.0

func (c *Cortex) DivergenceCount() (int, error)

DivergenceCount returns the number of unresolved divergence traces.

func (*Cortex) Events added in v0.3.0

func (c *Cortex) Events(traceID string) ([]event.Event, error)

Events returns the event log for a specific trace, ordered chronologically.

func (*Cortex) EventsSince added in v0.3.0

func (c *Cortex) EventsSince(afterID string, limit int) ([]event.Event, error)

EventsSince returns events after the given ULID cursor, up to limit.

func (*Cortex) Get

func (c *Cortex) Get(id string) (*Row, error)

func (*Cortex) GetClock added in v0.3.0

func (c *Cortex) GetClock() (federation.VClock, error)

GetClock returns the current vector clock.

func (*Cortex) List

func (c *Cortex) List(opts ListOptions) ([]Row, error)

func (*Cortex) MergeClock added in v0.3.0

func (c *Cortex) MergeClock(remote federation.VClock) error

MergeClock merges a remote vector clock into the local clock.

func (*Cortex) Purge added in v0.2.0

func (c *Cortex) Purge(days int) error

Purge permanently deletes traces that have been in the trash for more than days days. A days value of 0 is treated as 30.

func (*Cortex) Recover added in v0.2.0

func (c *Cortex) Recover(id string) error

Recover moves a trace out of the trash and back to the active traces directory.

func (*Cortex) Remove

func (c *Cortex) Remove(id string) error

Remove permanently deletes a trace from disk and the database. Use Trash for recoverable deletion.

func (*Cortex) ReplayEvent added in v0.3.0

func (c *Cortex) ReplayEvent(e event.Event) error

ReplayEvent materializes a remote event locally without emitting a new event. The remote event is stored in the local log with its original ID and origin.

func (*Cortex) ResolveDivergence added in v0.3.0

func (c *Cortex) ResolveDivergence(divergenceID, acceptOrigin, customBody string) error

ResolveDivergence resolves a divergence trace by either picking one of the versions stored in the divergence body (by origin name) or applying a caller-supplied custom merge. Exactly one of acceptOrigin or customBody must be non-empty. The divergence trace is trashed once the original is updated.

func (*Cortex) Search

func (c *Cortex) Search(query string, opts ListOptions) ([]Row, error)

func (*Cortex) SetForceSourceLock added in v0.5.0

func (c *Cortex) SetForceSourceLock(v bool)

SetForceSourceLock enables or disables the source-lock override. When enabled, mutations on source-locked traces succeed with a warning instead of being refused. Intended for CLI --force flags only.

func (*Cortex) Sync added in v0.2.2

func (c *Cortex) Sync() (SyncResult, error)

Sync reconciles the database with the current state of the markdown files on disk. It walks traces/, archive/traces/, and trash/traces/, upserts every file it finds, and reports orphaned DB rows (not deleted — just reported).

func (*Cortex) SyncWithOptions added in v0.3.0

func (c *Cortex) SyncWithOptions(opts SyncOptions) (SyncResult, error)

SyncWithOptions is Sync with explicit options. See SyncOptions.

func (*Cortex) TraceFile

func (c *Cortex) TraceFile(id string, archived bool) string

TraceFile returns the absolute path to a trace's markdown file.

func (*Cortex) TracesDir

func (c *Cortex) TracesDir() string

func (*Cortex) Trash added in v0.2.0

func (c *Cortex) Trash(id string) error

Trash moves a trace to the trash directory for deferred deletion.

func (*Cortex) TrashDir added in v0.2.0

func (c *Cortex) TrashDir() string

func (*Cortex) TrashFile added in v0.2.0

func (c *Cortex) TrashFile(id string) string

TrashFile returns the path for a trace in the trash.

func (*Cortex) Unarchive

func (c *Cortex) Unarchive(id string) error

func (*Cortex) Update

func (c *Cortex) Update(id string) error

Update rewrites an existing trace's DB row and FTS entry from its (potentially edited) markdown file on disk.

type FederationConfig added in v0.3.0

type FederationConfig struct {
	Mode     string      `yaml:"mode,omitempty"` // sync | publish | subscribe
	Peers    []PeerEntry `yaml:"peers,omitempty"`
	Interval string      `yaml:"interval,omitempty"` // e.g. "30s", "1m"
}

FederationConfig holds peer declarations for cortex.md.

func (*FederationConfig) EffectiveMode added in v0.5.0

func (fc *FederationConfig) EffectiveMode() string

EffectiveMode returns the configured federation mode, defaulting to "sync".

type ListOptions

type ListOptions struct {
	Type     string
	Author   string
	Tag      string
	Origin   string
	Archived bool // only archived (excludes trashed)
	Trashed  bool // only trashed
	All      bool // active + archived (excludes trashed)
}

type Manifest

type Manifest struct {
	ID         string            `yaml:"id,omitempty"`
	Name       string            `yaml:"name"`
	Purpose    string            `yaml:"purpose,omitempty"`
	Owner      string            `yaml:"owner,omitempty"`
	Created    string            `yaml:"created"`
	Version    int               `yaml:"version"`
	Access     *AccessConfig     `yaml:"access,omitempty"`
	Federation *FederationConfig `yaml:"federation,omitempty"`
}

Manifest is the cortex.md file at the root of each Cortex.

func Create

func Create(name, dir string) (Manifest, error)

Create initialises a new Cortex on disk and registers it. dir is the parent directory; the cortex is created as dir/<name>/. Returns the freshly written manifest so callers can surface the new cortex's ULID to the user (see `noema init`).

func ReadManifest added in v0.2.2

func ReadManifest(dir string) (Manifest, error)

ReadManifest parses the cortex.md manifest in the given cortex directory.

func (Manifest) PeerLabelCollidesWithSelf added in v0.3.0

func (m Manifest) PeerLabelCollidesWithSelf(peerLabel string) bool

PeerLabelCollidesWithSelf reports whether the proposed peer label is the same as this cortex's own name. This is a federation safety guardrail: even after the cortex-id migration (docs/design/cortex-uuid-plan.md), a label collision is confusing in display surfaces and should be rejected at config time.

func (Manifest) ValidateFederation added in v0.5.0

func (m Manifest) ValidateFederation() error

ValidateFederation checks that the federation mode and per-peer modes in the manifest are recognized values. Returns nil when there is no federation block or when all values are valid.

type PeerEntry added in v0.3.0

type PeerEntry struct {
	Name     string `yaml:"name"`
	Endpoint string `yaml:"endpoint"`
	CA       string `yaml:"ca,omitempty"`   // path to CA cert for TLS verification
	Mode     string `yaml:"mode,omitempty"` // sync | paused
}

PeerEntry is a peer declared in cortex.md.

func (PeerEntry) EffectiveMode added in v0.5.0

func (pe PeerEntry) EffectiveMode() string

EffectiveMode returns the configured peer mode, defaulting to "sync".

type Row

type Row struct {
	ID           string
	Title        string
	Type         string
	Author       string
	Origin       string
	Tags         []string
	DerivedFrom  []string
	ArchivedAt   string
	TrashedAt    string
	CreatedAt    string
	UpdatedAt    string
	ContentHash  string
	SourceLocked bool
	SourceHash   string
}

Row is a DB row joined with tags, returned by list/search operations.

type SyncOptions added in v0.3.0

type SyncOptions struct {
	// Recover, when true, attempts to rebuild missing files for orphaned DB
	// rows from the local event log. Off by default so manual `rm` of a trace
	// file remains a valid way to mark it for cleanup.
	Recover bool
}

SyncOptions controls optional Sync behaviors.

type SyncResult added in v0.2.2

type SyncResult struct {
	Added     int // files found on disk but not in DB
	Updated   int // files found on disk and already in DB (re-synced)
	Recovered int // orphaned DB rows whose files were rebuilt from the event log
	Orphaned  int // IDs in DB with no corresponding file on disk (after recovery)
}

SyncResult summarises what Sync found.

Jump to

Keyboard shortcuts

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