testharness

package
v0.1.164 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package testharness provides in-process test scaffolding for the permission system. It exists so unit tests of guards, interceptors, and plugin code can assert PDP behavior WITHOUT spinning up a real saas-starter (which lives in a separate repo and needs Postgres).

What's here:

  • FakePDP: programmable decisions + a recorded call log. Use this when a unit test needs "PDP says allow on action X, deny on action Y" without caring how the decisions are made.

  • PrincipalBuilder: ergonomic construction of test Principals (humans, services, agents) for stamping into context.

  • DelegationBuilder: build delegation chains for tests of escalation / sub-agent flows.

What's NOT here (yet):

  • SaaSFixture: a Postgres + saas-starter API harness. Lives in M0 phase 2 once the saas-starter Principal/Decide RPCs land. For now, integration tests against saas-starter live alongside the saas-starter codebase, not here.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FakeCall

type FakeCall struct {
	Toolbox  string
	Tool     string
	Args     map[string]any
	Identity map[string]any
	Decision policy.PDPDecision // what the FakePDP returned
}

FakeCall is one recorded Evaluate. The fields are immutable snapshots — callers can hold them safely after Calls() returns.

type FakePDP

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

FakePDP is a programmable PDP for unit tests. It records every call so tests can assert what was asked, AND it returns a decision determined by either:

  1. An exact-match rule (Tool == request.Tool AND Toolbox == request.Toolbox)
  2. A toolbox-match rule (Toolbox == request.Toolbox, Tool == "")
  3. The default decision (set by NewFakePDP)

First match in the rules slice wins, in the order rules were added.

Concurrency: safe. Tests that fire goroutines at the PDP can read Calls() after the fact to assert what happened.

func NewFakeAllow

func NewFakeAllow() *FakePDP

NewFakeAllow returns a FakePDP whose default is allow. Use when the test cares about specific denies; everything else is permitted.

func NewFakeDeny

func NewFakeDeny() *FakePDP

NewFakeDeny returns a FakePDP whose default is deny with a recognizable reason. Use when the test cares about specific allows; everything else is refused. Reason includes "fake-pdp" substring so failure messages clearly show the gate is the test fixture, not a misconfigured production PDP.

func NewFakePDP

func NewFakePDP(defaultDecision policy.PDPDecision) *FakePDP

NewFakePDP returns a FakePDP whose default (when no rule matches) is the supplied decision. Most tests use NewFakeAllow or NewFakeDeny rather than this directly.

func (*FakePDP) AllowTool

func (f *FakePDP) AllowTool(toolbox, tool string) *FakePDP

AllowTool installs a rule allowing a specific tool on the named toolbox. Both must match exactly. Wildcards are not supported in the fake — tests that need pattern matching should configure multiple explicit rules.

func (*FakePDP) AllowToolbox

func (f *FakePDP) AllowToolbox(toolbox string) *FakePDP

AllowToolbox installs a rule allowing all tools on the named toolbox. Returns the receiver for chaining.

func (*FakePDP) CallCount

func (f *FakePDP) CallCount() int

CallCount returns the number of Evaluate calls observed. Cheaper than Calls() when the test only needs a count.

func (*FakePDP) Calls

func (f *FakePDP) Calls() []FakeCall

Calls returns a snapshot of every Evaluate call observed so far. Returned slice is safe to retain — it's a copy.

func (*FakePDP) DenyTool

func (f *FakePDP) DenyTool(toolbox, tool, reason string) *FakePDP

DenyTool installs a rule denying a specific tool with a reason. Reason MUST be non-empty — silent denials are a debugging nightmare; force the test author to write what they're asserting.

func (*FakePDP) DenyToolbox

func (f *FakePDP) DenyToolbox(toolbox, reason string) *FakePDP

DenyToolbox installs a rule denying all tools on the named toolbox with the given reason. Empty reason gets a defaulted message.

func (*FakePDP) Evaluate

func (f *FakePDP) Evaluate(_ context.Context, req *policy.PDPRequest) policy.PDPDecision

Evaluate implements policy.PDP. Records the call, returns the matched decision (or default).

func (*FakePDP) LastCall

func (f *FakePDP) LastCall() FakeCall

LastCall returns the most recent FakeCall, panicking if none have been recorded. Tests that assert on a single call use this for concise assertions: pdp.LastCall().Tool == "git.status".

func (*FakePDP) Reset

func (f *FakePDP) Reset()

Reset clears the call log without removing rules. Useful when a single test case spans multiple "phases" and wants to assert calls per phase.

type PrincipalBuilder

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

PrincipalBuilder constructs test Principals fluently. The default (zero-value Builder) gives a valid human principal in org "test-org" with a generated ID — useful when the test doesn't care who, just that there IS a principal.

Usage:

p := testharness.NewPrincipalBuilder().AsAgent("auto-merge", "0.1.0").Build()
ctx := policy.WithPrincipal(context.Background(), p)

func NewPrincipalBuilder

func NewPrincipalBuilder() *PrincipalBuilder

NewPrincipalBuilder returns a builder with sensible defaults: a human principal in "test-org" with a unique generated ID.

func (*PrincipalBuilder) AsAgent

func (b *PrincipalBuilder) AsAgent(name, version string) *PrincipalBuilder

AsAgent switches kind to agent and sets AgentID to the canonical "publisher/name:version" form. Tests should pass non-empty name + version; we fill in publisher as "test.codefly.dev" if not specified via WithAgentPublisher.

func (*PrincipalBuilder) AsHuman

func (b *PrincipalBuilder) AsHuman() *PrincipalBuilder

AsHuman switches kind to human, clearing any previously-set agent fields. Default; rarely called explicitly.

func (*PrincipalBuilder) AsService

func (b *PrincipalBuilder) AsService() *PrincipalBuilder

AsService switches kind to service. Use for test fixtures representing CI runners, deployment bots without per-version identity, etc.

func (*PrincipalBuilder) Build

func (b *PrincipalBuilder) Build() *policy.Principal

Build produces the Principal. Panics on Validate failure — tests should fail loud if the builder produced something nonsensical.

func (*PrincipalBuilder) DelegatedFrom

func (b *PrincipalBuilder) DelegatedFrom(principalID, kind, displayName, grantID string) *PrincipalBuilder

DelegatedFrom appends a link to the delegation chain. Multiple calls build a chain in the order they were called (oldest first).

Example: a sub-agent acting under user antoine's authority who herself delegated through Mind:

NewPrincipalBuilder().AsAgent("merger", "0.1.0").
    DelegatedFrom("user-antoine", policy.KindHuman, "antoine", "grant-1").
    DelegatedFrom("agent-mind", policy.KindAgent, "Mind", "grant-2").
    Build()

func (*PrincipalBuilder) ExpiringIn

func (b *PrincipalBuilder) ExpiringIn(d time.Duration) *PrincipalBuilder

ExpiringIn sets ExpiresAt to now+d. Use this rather than WithExpiresAt when the test only cares about "expires soon" / "expires far in the future" relative timing.

func (*PrincipalBuilder) WithAgentID

func (b *PrincipalBuilder) WithAgentID(id string) *PrincipalBuilder

WithAgentID overrides the auto-built AgentID. Use when the test needs an exact identifier (e.g. matching a real plugin manifest).

func (*PrincipalBuilder) WithDisplayName

func (b *PrincipalBuilder) WithDisplayName(name string) *PrincipalBuilder

WithDisplayName sets the human-readable name surfaced in audit / approval UI.

func (*PrincipalBuilder) WithExpiresAt

func (b *PrincipalBuilder) WithExpiresAt(t time.Time) *PrincipalBuilder

WithExpiresAt sets the absolute expiry. Used by tests that drive IsExpiredAt with a fixed clock.

func (*PrincipalBuilder) WithID

func (b *PrincipalBuilder) WithID(id string) *PrincipalBuilder

WithID overrides the auto-generated ID. Use when the test must assert a specific principal_id appearing in audit / PDP calls.

func (*PrincipalBuilder) WithOrg

func (b *PrincipalBuilder) WithOrg(orgID string) *PrincipalBuilder

WithOrg sets the organization. Defaults to "test-org".

func (*PrincipalBuilder) WithToken

func (b *PrincipalBuilder) WithToken(tok string) *PrincipalBuilder

WithToken sets the credential string. Tests of token-aware paths (PDP that re-verifies caveats, audit that logs the token id) need this to be a real-shaped token; tests of pure auth flow can leave it as the empty default.

Jump to

Keyboard shortcuts

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