extension

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2026 License: AGPL-3.0 Imports: 2 Imported by: 0

Documentation

Overview

Package extension holds the core's in-process extension seams: the small, stable set of interfaces (plus no-op defaults) a wrapper can implement to add behavior without modifying the core. It is the ONLY package outside internal/ — everything else stays unimportable on purpose — because a separate module must be able to name these types and inject implementations (see docs/extending.md). Keep this package tiny: interfaces and no-op structs, no behavior. Adding to it is API surface and a potential breaking change for wrappers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AllowAll

type AllowAll struct{}

AllowAll is the no-op default: every request proceeds.

func (AllowAll) Allow

type Discard

type Discard struct{}

Discard is the no-op default: usage signals are dropped.

func (Discard) RecordIngested

func (Discard) RecordIngested(context.Context, string, int)

type Entitlement

type Entitlement interface {
	// AllowAnalysis reports whether projectID may use the analysis surfaces
	// right now. reason is a short human-readable hint surfaced on denial
	// (the 402 body / MCP tool error); empty selects a generic default. On
	// deny the core returns 402 on the API/MCP surfaces and redirects the web
	// playground to the wrapper's upgrade URL, and the handler never runs.
	AllowAnalysis(ctx context.Context, projectID string) (ok bool, reason string)
}

Entitlement gates the read/analysis surfaces — the REST query + schema endpoints, the MCP query + schema tools, and the web query playground — after the project has been resolved. The core ships Unlimited (every project may analyze). It is consulted ONLY on those analysis surfaces; ingest is never gated, so a hosted build can keep accepting a tenant's events while denying analysis until they pay. AllowAnalysis MUST be safe for concurrent use and MUST NOT block beyond a small, bounded check.

type LimitKey

type LimitKey struct {
	Surface   string // "ingest" | "query" | "mcp"
	ProjectID string // resolved tenant; "" before resolution
	UserID    string // bearer surfaces only; "" for ingest
	TokenID   string // opaque credential id, for per-credential limits
	RemoteIP  string
}

LimitKey identifies what is being rate-limited. Fields are populated at the point in the chain where identity is known; a limiter uses whichever it needs. ProjectID is set once the public ingest token or OAuth grant has resolved.

type RateLimiter

type RateLimiter interface {
	// Allow reports whether the request may proceed now. retryAfter is a hint
	// for the 429 Retry-After header when ok is false (zero = omit).
	Allow(ctx context.Context, key LimitKey) (ok bool, retryAfter time.Duration)
}

RateLimiter decides whether a request may proceed. The core ships AllowAll. Allow MUST be safe for concurrent use and MUST NOT block on the hot path beyond a small bounded check.

type Unlimited

type Unlimited struct{}

Unlimited is the no-op default: every project may analyze.

func (Unlimited) AllowAnalysis

func (Unlimited) AllowAnalysis(context.Context, string) (bool, string)

type UsageSink

type UsageSink interface {
	RecordIngested(ctx context.Context, projectID string, events int)
}

UsageSink receives a usage signal each time the ingest pipeline durably accepts events for a project. The core ships Discard. RecordIngested is called off the request hot path (after the batch lands in ClickHouse), so a hosted implementation may do real work, but MUST NOT panic and SHOULD NOT block the flusher for long.

Jump to

Keyboard shortcuts

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