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 ¶
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 ¶
func Register( d *dispatcher.Dispatcher, reg dashcontract.Registry, wreg dashcontract.WardenRegistry, deps Deps, ) error
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.
Source Files
¶
- contract.go
- enforcement.go
- errors.go
- handlers_key_create.go
- handlers_key_rotate.go
- handlers_key_scopes.go
- handlers_key_state.go
- handlers_keys.go
- handlers_overview.go
- handlers_pickers.go
- handlers_policies.go
- handlers_policy_write.go
- handlers_rotations.go
- handlers_scope_write.go
- handlers_settings.go
- handlers_usage.go
- load.go
- project.go
- tenant.go