contract

package
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package contract wires keysmith into the Forge dashboard's contract path. It registers the `keysmith` contributor with the dashboard's contract registry and answers the queries and commands the React plugin sends.

Index

Constants

View Source
const ContributorName = "keysmith"

ContributorName is the name keysmith registers under with the dashboard's contract registry. It is also the namespace of every intent in the manifest.

Variables

This section is empty.

Functions

func Register

Register loads the embedded manifest, validates it, registers the keysmith contributor with reg, and binds the handlers against deps.

Types

type Deps

type Deps struct {
	// Engine is the keysmith engine every handler reads and writes through.
	Engine *keysmith.Engine

	// DefaultTenantID is the tenant a request belongs to when the principal
	// carries no tenant_id claim and the context carries no forge Scope with
	// an org. Under an auth extension that sets the session's org, it only
	// answers for sessions without one. Leaving it empty makes those requests
	// refuse, which is correct: the empty string would match every tenant's
	// rows.
	DefaultTenantID string

	// DefaultAppID labels new rows when the principal carries no app_id
	// claim. It may be empty. Keysmith never filters by app, so a wrong or
	// missing app only mislabels a new row and never widens a read.
	DefaultAppID string

	// Plugins names the hook plugins the host registered. The settings
	// intent lists them, and the key detail uses it to decide whether to
	// link to Warden.
	Plugins []string

	// Logger receives the server-side detail of internal errors. It may be
	// nil, in which case nothing is logged.
	Logger forge.Logger
}

Deps is everything the contract handlers need from the running extension.

type EnforcementRow

type EnforcementRow struct {
	Field    string `json:"field"`
	Label    string `json:"label"`
	Group    string `json:"group"`
	Enforced bool   `json:"enforced"`
	When     string `json:"when"`
}

EnforcementRow says whether this deployment enforces one policy field, and when. Field is the wire name the policy commands take. Label is the editor's label for it. Group is the editor's group: "keysmith" (enforced by Keysmith), "rateLimiter" (enforced only with a rate limiter) or "application" (stored for the host application, never checked here). When is set exactly when Enforced is true.

type KeySummary

type KeySummary struct {
	ID             string   `json:"id"`
	Name           string   `json:"name"`
	Description    string   `json:"description,omitempty"`
	Prefix         string   `json:"prefix"`
	Hint           string   `json:"hint"`
	Environment    string   `json:"environment"`
	State          string   `json:"state"`          // as stored
	EffectiveState string   `json:"effectiveState"` // what the page shows
	ExpiryPending  bool     `json:"expiryPending"`  // expired, not yet marked
	ExpiresSoon    bool     `json:"expiresSoon"`    // active, expires within 7 days
	PolicyID       string   `json:"policyId,omitempty"`
	Scopes         []string `json:"scopes"`
	CreatedBy      string   `json:"createdBy,omitempty"`
	ExpiresAt      string   `json:"expiresAt,omitempty"`
	LastUsedAt     string   `json:"lastUsedAt,omitempty"`
	RotatedAt      string   `json:"rotatedAt,omitempty"`
	RevokedAt      string   `json:"revokedAt,omitempty"`
	CreatedAt      string   `json:"createdAt"`
	UpdatedAt      string   `json:"updatedAt"`
}

KeySummary is the public shape of a key. It carries the hint (the last four characters of the raw key) and never the raw key or its hash.

type PolicyDetail

type PolicyDetail struct {
	ID                     string   `json:"id"`
	Name                   string   `json:"name"`
	Description            string   `json:"description,omitempty"`
	MaxKeyLifetimeSeconds  *int64   `json:"maxKeyLifetimeSeconds"`
	GraceSeconds           *int64   `json:"graceSeconds"`
	AllowedScopes          []string `json:"allowedScopes"`
	RateLimit              *int64   `json:"rateLimit"`
	RateLimitWindowSeconds *int64   `json:"rateLimitWindowSeconds"`
	BurstLimit             *int64   `json:"burstLimit"`
	AllowedIPs             []string `json:"allowedIps"`
	AllowedOrigins         []string `json:"allowedOrigins"`
	AllowedMethods         []string `json:"allowedMethods"`
	AllowedPaths           []string `json:"allowedPaths"`
	RotationPeriodSeconds  *int64   `json:"rotationPeriodSeconds"`
	DailyQuota             *int64   `json:"dailyQuota"`
	MonthlyQuota           *int64   `json:"monthlyQuota"`
	CreatedAt              string   `json:"createdAt"`
	UpdatedAt              string   `json:"updatedAt"`
}

PolicyDetail is every policy field the editor and the detail page show. Counts and durations follow PolicyRef: zero means unset to the engine, so it goes out as an explicit null. Lists go out sorted, without duplicates, and as [] when empty, never null. Durations are whole seconds.

type PolicyRef

type PolicyRef struct {
	ID                    string `json:"id"`
	Name                  string `json:"name"`
	MaxKeyLifetimeSeconds *int64 `json:"maxKeyLifetimeSeconds"`
	GraceSeconds          *int64 `json:"graceSeconds"`
}

PolicyRef is the slice of a policy a key's page needs. The engine reads a zero grace as "not set" (RotateKey then uses 24h) and a zero lifetime as "no maximum", so both go out as an explicit null, never as 0.

type PolicySummary

type PolicySummary struct {
	ID                    string   `json:"id"`
	Name                  string   `json:"name"`
	Description           string   `json:"description,omitempty"`
	MaxKeyLifetimeSeconds *int64   `json:"maxKeyLifetimeSeconds"`
	GraceSeconds          *int64   `json:"graceSeconds"`
	AllowedScopes         []string `json:"allowedScopes"` // never nil
}

PolicySummary is a policy as the key forms' picker shows it. Grace and lifetime follow PolicyRef: an unset value goes out as an explicit null.

type PreviousKey

type PreviousKey struct {
	RotationID string `json:"rotationId"`
	Hint       string `json:"hint"`
	Reason     string `json:"reason"`
	RotatedAt  string `json:"rotatedAt"`
	GraceEnds  string `json:"graceEnds"`
}

PreviousKey is an open rotation window: the old key still validates until GraceEnds. Only the old key's hint is shown.

type RotationItem

type RotationItem struct {
	ID    string `json:"id"`
	KeyID string `json:"keyId"`
	// KeyName, Prefix and Environment are null together when the key no
	// longer exists in this tenant.
	KeyName     *string `json:"keyName"`
	Prefix      *string `json:"prefix"`
	Environment *string `json:"environment"`
	// OldHint and NewHint are "" on records written before hints existed.
	OldHint string `json:"oldHint"`
	NewHint string `json:"newHint"`
	Reason  string `json:"reason"`
	// GraceSeconds is the window the rotation recorded. 0 is a real
	// zero-grace rotation, not unset, so it goes out as 0, never null.
	GraceSeconds int64  `json:"graceSeconds"`
	GraceEnds    string `json:"graceEnds"`
	// WindowOpen is true while the previous key can still validate: the key
	// exists in this tenant, is neither expired nor revoked, and is not past
	// its expiry; the record has an old hint; and GraceEnds is ahead of now.
	// A suspended key's window stays open while its expiry is ahead, since
	// it resumes on reactivation.
	WindowOpen bool   `json:"windowOpen"`
	RotatedBy  string `json:"rotatedBy,omitempty"`
	RotatedAt  string `json:"rotatedAt"` // the record's CreatedAt
}

RotationItem is one rotation as the Rotations page and the key page's history show it. Masked forms are built on the client from prefix, environment and the hints. Neither key's hash is ever carried.

type ScopeSummary

type ScopeSummary struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Parent      string `json:"parent,omitempty"`
	Description string `json:"description,omitempty"`
}

ScopeSummary is a scope as the key forms' picker shows it.

type UsageBucket

type UsageBucket struct {
	Start        string `json:"start"`        // RFC3339 UTC bucket start
	Requests     int64  `json:"requests"`     // every recorded request
	ClientErrors int64  `json:"clientErrors"` // status 400 to 499
	ServerErrors int64  `json:"serverErrors"` // status 500 and up
	Succeeded    int64  `json:"succeeded"`    // status below 400
	// AvgLatencyMs is the mean latency rounded down, and null for an empty
	// bucket, where there is nothing to average.
	AvgLatencyMs *int64 `json:"avgLatencyMs"`
}

UsageBucket is one period of a usage series. Every bucket in the range is present, empty ones included, so a chart never has to fill gaps.

type UsageRecordItem

type UsageRecordItem struct {
	ID         string `json:"id"`
	KeyID      string `json:"keyId"`
	Method     string `json:"method"`
	Endpoint   string `json:"endpoint"`
	StatusCode int    `json:"statusCode"`
	LatencyMs  int64  `json:"latencyMs"`
	IPAddress  string `json:"ipAddress,omitempty"`
	At         string `json:"at"`
}

UsageRecordItem is one recorded request. The user agent and metadata stay out: the page does not show them, and metadata is whatever the application chose to attach.

Jump to

Keyboard shortcuts

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