Files
multica/server/pkg/db/generated/models.go
Bohan Jiang 2323b72710 feat(autopilots): webhook delivery layer + idempotency/signature/replay (MUL-2334) [PR1] (#2774)
* feat(autopilots): webhook delivery layer + idempotency / signature / replay (MUL-2334)

Splits "inbound webhook receipt" from "autopilot run creation" so we can
record duplicate attempts, signature outcomes, and ignored/skipped
deliveries — and replay a delivery on demand. v1 ingress wrote straight
into autopilot_run.trigger_payload, which collapsed the two concerns and
left run_only autopilots vulnerable to provider retry storms.

Backend only (PR1). UI Deliveries tab follows in PR2.

Schema (migration 093):
  - autopilot_trigger.provider: 'generic' | 'github' (default 'generic').
  - autopilot_trigger.signing_secret: nullable plaintext (HMAC needs it
    cleartext; mirrors how webhook_token is stored).
  - webhook_delivery: one row per inbound POST. Carries raw_body,
    selected_headers, dedupe_key/source, signature_status,
    autopilot_run_id, replayed_from_delivery_id, response_status / body.
  - Partial unique index on (trigger_id, dedupe_key) excludes NULL and
    'rejected' rows, so a wrong-secret 401 does NOT permanently block a
    future retry with the same X-GitHub-Delivery once the operator fixes
    the secret.

Ingress flow (autopilot_webhook.go), persist-first + sync dispatch:
  1. IP rate limit -> 2. token lookup -> 3. token rate limit ->
  4. read raw body -> 5. autopilot/workspace cross-check ->
  6. normalize JSON (400 without persistence on parse failure) ->
  7. compute dedupe key + signature status ->
  8. INSERT delivery (status=queued). On (trigger_id, dedupe_key)
     unique-violation: bump attempt_count on existing row and return
     the original delivery_id + autopilot_run_id with 200 ->
  9. invalid/missing signature: UPDATE -> rejected, return 401 with
     delivery_id (no dispatch, not replayable) ->
 10. trigger disabled / autopilot paused/archived: UPDATE -> ignored,
     return 200 ->
 11. DispatchAutopilot synchronously, UPDATE -> dispatched/skipped/failed
     with autopilot_run_id and the response body we returned ->
 12. TouchAutopilotTriggerFiredAt and return 200.

No new long-running worker. A stale 'queued' row only happens if the
process dies between INSERT and UPDATE; that's a follow-up sweeper, not
this PR.

Authenticated API:
  - GET    /api/autopilots/{id}/deliveries (slim list)
  - GET    /api/autopilots/{id}/deliveries/{deliveryId} (with raw_body)
  - POST   /api/autopilots/{id}/deliveries/{deliveryId}/replay -> creates
    a new delivery row (replayed_from_delivery_id set), dispatches a
    new run, never collapses onto the original via dedupe.
  - PUT    /api/autopilots/{id}/triggers/{triggerId}/signing-secret
    Write-only; trigger response surfaces has_signing_secret +
    signing_secret_hint (last 4 chars), never the secret itself.

Signature verification reuses the GitHub-compatible
X-Hub-Signature-256: sha256=<hex(hmac(body, secret))> scheme; the
HMAC helper is constant-time. Invalid/missing signatures still count
against per-IP and per-token rate limits.

autopilot_run.trigger_payload is intentionally preserved — delivery
records the HTTP receipt; run records the normalized envelope handed
to the agent. They are two different views.

Tests (Postgres-backed):
  - delivery persistence on accept
  - dedupe via Idempotency-Key and X-GitHub-Delivery; run_only retry
    storm pin (3 retries -> 1 run)
  - invalid signature: 401 + rejected row + no run linkage
  - missing signature when secret configured: 401 + 'missing' state
  - valid signature dispatches
  - signing secret never echoed in trigger responses; hint shows last 4
  - min-length and clear-by-empty for signing secret PUT
  - replay creates a NEW delivery + new run; rejected deliveries cannot
    be replayed
  - list omits raw_body; detail includes it; cross-autopilot ID returns
    404 (workspace isolation defense in depth)
  - provider validation: unknown -> 400, github -> 201 round-trips
  - bad-signature stream still counts against per-token rate limit

Co-authored-by: multica-agent <github@multica.ai>

* fix(autopilots): address PR review on webhook delivery layer (MUL-2334)

- Exclude `failed` from the (trigger_id, dedupe_key) partial unique index
  alongside `rejected`, so a transient ingress failure does not strand the
  provider's stable X-GitHub-Delivery / Idempotency-Key retry. Update the
  dedupe lookup to prefer non-terminal rows under the same predicate.
- Tighten delivery status enum: drop `skipped` from the CHECK constraint
  and from the handler. A run that was admission-skipped (e.g. runtime
  offline) is now recorded as delivery=`dispatched` linked to the
  skipped run, with the response payload carrying status=`skipped`.
  Source of truth for skipped-ness is autopilot_run.status, not the
  delivery row — keeps the Deliveries UI enum unambiguous.
- On dispatch error, link the (possibly non-nil) autopilot_run returned
  by DispatchAutopilot to the failed delivery so Deliveries UI can
  navigate to the run row for debugging.
- Slim list projection: ListWebhookDeliveriesByAutopilot no longer pulls
  raw_body / selected_headers / response_body — a 100-row page × 256 KiB
  would otherwise round-trip ~25 MiB from Postgres per Deliveries reload.
  Detail endpoint continues to return the full row.
- Fix backend CI: TestGetDelivery_ReturnsFullPayload now decodes the
  response and asserts on the parsed raw_body instead of substring-
  matching against an escaped JSON string; raise the test-suite default
  webhook rate limits in TestMain so the shared 192.0.2.1 IP bucket
  doesn't fill across the suite and leak 429s into unrelated tests.
- Add regression coverage for the dedupe-after-failure path.

cd server && go test ./... is green locally.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-05-18 14:59:40 +08:00

660 lines
28 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
package db
import (
"github.com/jackc/pgx/v5/pgtype"
)
type ActivityLog struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
IssueID pgtype.UUID `json:"issue_id"`
ActorType pgtype.Text `json:"actor_type"`
ActorID pgtype.UUID `json:"actor_id"`
Action string `json:"action"`
Details []byte `json:"details"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type Agent struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
AvatarUrl pgtype.Text `json:"avatar_url"`
RuntimeMode string `json:"runtime_mode"`
RuntimeConfig []byte `json:"runtime_config"`
Visibility string `json:"visibility"`
Status string `json:"status"`
MaxConcurrentTasks int32 `json:"max_concurrent_tasks"`
OwnerID pgtype.UUID `json:"owner_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Description string `json:"description"`
RuntimeID pgtype.UUID `json:"runtime_id"`
Instructions string `json:"instructions"`
ArchivedAt pgtype.Timestamptz `json:"archived_at"`
ArchivedBy pgtype.UUID `json:"archived_by"`
CustomEnv []byte `json:"custom_env"`
CustomArgs []byte `json:"custom_args"`
McpConfig []byte `json:"mcp_config"`
Model pgtype.Text `json:"model"`
}
type AgentRuntime struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
DaemonID pgtype.Text `json:"daemon_id"`
Name string `json:"name"`
RuntimeMode string `json:"runtime_mode"`
Provider string `json:"provider"`
Status string `json:"status"`
DeviceInfo string `json:"device_info"`
Metadata []byte `json:"metadata"`
LastSeenAt pgtype.Timestamptz `json:"last_seen_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
OwnerID pgtype.UUID `json:"owner_id"`
LegacyDaemonID pgtype.Text `json:"legacy_daemon_id"`
// IANA timezone (e.g. 'Asia/Shanghai'). Bucket boundary for per-day and per-hour token usage aggregation. Defaults to UTC for runtimes that existed before MUL-1950; the daemon registration / web UI overwrites this with an operator-detected value going forward.
Timezone string `json:"timezone"`
Visibility string `json:"visibility"`
}
type AgentSkill struct {
AgentID pgtype.UUID `json:"agent_id"`
SkillID pgtype.UUID `json:"skill_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type AgentTaskQueue struct {
ID pgtype.UUID `json:"id"`
AgentID pgtype.UUID `json:"agent_id"`
IssueID pgtype.UUID `json:"issue_id"`
Status string `json:"status"`
Priority int32 `json:"priority"`
DispatchedAt pgtype.Timestamptz `json:"dispatched_at"`
StartedAt pgtype.Timestamptz `json:"started_at"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
Result []byte `json:"result"`
Error pgtype.Text `json:"error"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
Context []byte `json:"context"`
RuntimeID pgtype.UUID `json:"runtime_id"`
SessionID pgtype.Text `json:"session_id"`
WorkDir pgtype.Text `json:"work_dir"`
TriggerCommentID pgtype.UUID `json:"trigger_comment_id"`
ChatSessionID pgtype.UUID `json:"chat_session_id"`
AutopilotRunID pgtype.UUID `json:"autopilot_run_id"`
Attempt int32 `json:"attempt"`
MaxAttempts int32 `json:"max_attempts"`
ParentTaskID pgtype.UUID `json:"parent_task_id"`
FailureReason pgtype.Text `json:"failure_reason"`
TriggerSummary pgtype.Text `json:"trigger_summary"`
ForceFreshSession bool `json:"force_fresh_session"`
IsLeaderTask bool `json:"is_leader_task"`
}
type Attachment struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
IssueID pgtype.UUID `json:"issue_id"`
CommentID pgtype.UUID `json:"comment_id"`
UploaderType string `json:"uploader_type"`
UploaderID pgtype.UUID `json:"uploader_id"`
Filename string `json:"filename"`
Url string `json:"url"`
ContentType string `json:"content_type"`
SizeBytes int64 `json:"size_bytes"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
ChatSessionID pgtype.UUID `json:"chat_session_id"`
ChatMessageID pgtype.UUID `json:"chat_message_id"`
}
type Autopilot struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
AssigneeID pgtype.UUID `json:"assignee_id"`
Status string `json:"status"`
ExecutionMode string `json:"execution_mode"`
IssueTitleTemplate pgtype.Text `json:"issue_title_template"`
CreatedByType string `json:"created_by_type"`
CreatedByID pgtype.UUID `json:"created_by_id"`
LastRunAt pgtype.Timestamptz `json:"last_run_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type AutopilotRun struct {
ID pgtype.UUID `json:"id"`
AutopilotID pgtype.UUID `json:"autopilot_id"`
TriggerID pgtype.UUID `json:"trigger_id"`
Source string `json:"source"`
Status string `json:"status"`
IssueID pgtype.UUID `json:"issue_id"`
TaskID pgtype.UUID `json:"task_id"`
TriggeredAt pgtype.Timestamptz `json:"triggered_at"`
CompletedAt pgtype.Timestamptz `json:"completed_at"`
FailureReason pgtype.Text `json:"failure_reason"`
TriggerPayload []byte `json:"trigger_payload"`
Result []byte `json:"result"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type AutopilotTrigger struct {
ID pgtype.UUID `json:"id"`
AutopilotID pgtype.UUID `json:"autopilot_id"`
Kind string `json:"kind"`
Enabled bool `json:"enabled"`
CronExpression pgtype.Text `json:"cron_expression"`
Timezone pgtype.Text `json:"timezone"`
NextRunAt pgtype.Timestamptz `json:"next_run_at"`
WebhookToken pgtype.Text `json:"webhook_token"`
Label pgtype.Text `json:"label"`
LastFiredAt pgtype.Timestamptz `json:"last_fired_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Provider string `json:"provider"`
SigningSecret pgtype.Text `json:"signing_secret"`
}
type ChatMessage struct {
ID pgtype.UUID `json:"id"`
ChatSessionID pgtype.UUID `json:"chat_session_id"`
Role string `json:"role"`
Content string `json:"content"`
TaskID pgtype.UUID `json:"task_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
FailureReason pgtype.Text `json:"failure_reason"`
ElapsedMs pgtype.Int8 `json:"elapsed_ms"`
}
type ChatSession struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
AgentID pgtype.UUID `json:"agent_id"`
CreatorID pgtype.UUID `json:"creator_id"`
Title string `json:"title"`
SessionID pgtype.Text `json:"session_id"`
WorkDir pgtype.Text `json:"work_dir"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
UnreadSince pgtype.Timestamptz `json:"unread_since"`
RuntimeID pgtype.UUID `json:"runtime_id"`
}
type Comment struct {
ID pgtype.UUID `json:"id"`
IssueID pgtype.UUID `json:"issue_id"`
AuthorType string `json:"author_type"`
AuthorID pgtype.UUID `json:"author_id"`
Content string `json:"content"`
Type string `json:"type"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ParentID pgtype.UUID `json:"parent_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
ResolvedAt pgtype.Timestamptz `json:"resolved_at"`
ResolvedByType pgtype.Text `json:"resolved_by_type"`
ResolvedByID pgtype.UUID `json:"resolved_by_id"`
}
type CommentReaction struct {
ID pgtype.UUID `json:"id"`
CommentID pgtype.UUID `json:"comment_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
ActorType string `json:"actor_type"`
ActorID pgtype.UUID `json:"actor_id"`
Emoji string `json:"emoji"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type DaemonConnection struct {
ID pgtype.UUID `json:"id"`
AgentID pgtype.UUID `json:"agent_id"`
DaemonID string `json:"daemon_id"`
Status string `json:"status"`
LastHeartbeatAt pgtype.Timestamptz `json:"last_heartbeat_at"`
RuntimeInfo []byte `json:"runtime_info"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type DaemonToken struct {
ID pgtype.UUID `json:"id"`
TokenHash string `json:"token_hash"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
DaemonID string `json:"daemon_id"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type Feedback struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Message string `json:"message"`
Metadata []byte `json:"metadata"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type GithubInstallation struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
InstallationID int64 `json:"installation_id"`
AccountLogin string `json:"account_login"`
AccountType string `json:"account_type"`
AccountAvatarUrl pgtype.Text `json:"account_avatar_url"`
ConnectedByID pgtype.UUID `json:"connected_by_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type GithubPullRequest struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
InstallationID int64 `json:"installation_id"`
RepoOwner string `json:"repo_owner"`
RepoName string `json:"repo_name"`
PrNumber int32 `json:"pr_number"`
Title string `json:"title"`
State string `json:"state"`
HtmlUrl string `json:"html_url"`
Branch pgtype.Text `json:"branch"`
AuthorLogin pgtype.Text `json:"author_login"`
AuthorAvatarUrl pgtype.Text `json:"author_avatar_url"`
MergedAt pgtype.Timestamptz `json:"merged_at"`
ClosedAt pgtype.Timestamptz `json:"closed_at"`
PrCreatedAt pgtype.Timestamptz `json:"pr_created_at"`
PrUpdatedAt pgtype.Timestamptz `json:"pr_updated_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
HeadSha string `json:"head_sha"`
MergeableState pgtype.Text `json:"mergeable_state"`
Additions int32 `json:"additions"`
Deletions int32 `json:"deletions"`
ChangedFiles int32 `json:"changed_files"`
}
type GithubPullRequestCheckSuite struct {
PrID pgtype.UUID `json:"pr_id"`
SuiteID int64 `json:"suite_id"`
HeadSha string `json:"head_sha"`
AppID int64 `json:"app_id"`
Conclusion pgtype.Text `json:"conclusion"`
Status string `json:"status"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type InboxItem struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
RecipientType string `json:"recipient_type"`
RecipientID pgtype.UUID `json:"recipient_id"`
Type string `json:"type"`
Severity string `json:"severity"`
IssueID pgtype.UUID `json:"issue_id"`
Title string `json:"title"`
Body pgtype.Text `json:"body"`
Read bool `json:"read"`
Archived bool `json:"archived"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
ActorType pgtype.Text `json:"actor_type"`
ActorID pgtype.UUID `json:"actor_id"`
Details []byte `json:"details"`
}
type Issue struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Status string `json:"status"`
Priority string `json:"priority"`
AssigneeType pgtype.Text `json:"assignee_type"`
AssigneeID pgtype.UUID `json:"assignee_id"`
CreatorType string `json:"creator_type"`
CreatorID pgtype.UUID `json:"creator_id"`
ParentIssueID pgtype.UUID `json:"parent_issue_id"`
AcceptanceCriteria []byte `json:"acceptance_criteria"`
ContextRefs []byte `json:"context_refs"`
Position float64 `json:"position"`
DueDate pgtype.Timestamptz `json:"due_date"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Number int32 `json:"number"`
ProjectID pgtype.UUID `json:"project_id"`
OriginType pgtype.Text `json:"origin_type"`
OriginID pgtype.UUID `json:"origin_id"`
FirstExecutedAt pgtype.Timestamptz `json:"first_executed_at"`
StartDate pgtype.Timestamptz `json:"start_date"`
}
type IssueDependency struct {
ID pgtype.UUID `json:"id"`
IssueID pgtype.UUID `json:"issue_id"`
DependsOnIssueID pgtype.UUID `json:"depends_on_issue_id"`
Type string `json:"type"`
}
type IssueLabel struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
Color string `json:"color"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type IssuePullRequest struct {
IssueID pgtype.UUID `json:"issue_id"`
PullRequestID pgtype.UUID `json:"pull_request_id"`
LinkedByType pgtype.Text `json:"linked_by_type"`
LinkedByID pgtype.UUID `json:"linked_by_id"`
LinkedAt pgtype.Timestamptz `json:"linked_at"`
}
type IssueReaction struct {
ID pgtype.UUID `json:"id"`
IssueID pgtype.UUID `json:"issue_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
ActorType string `json:"actor_type"`
ActorID pgtype.UUID `json:"actor_id"`
Emoji string `json:"emoji"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type IssueSubscriber struct {
IssueID pgtype.UUID `json:"issue_id"`
UserType string `json:"user_type"`
UserID pgtype.UUID `json:"user_id"`
Reason string `json:"reason"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type IssueToLabel struct {
IssueID pgtype.UUID `json:"issue_id"`
LabelID pgtype.UUID `json:"label_id"`
}
type Member struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
UserID pgtype.UUID `json:"user_id"`
Role string `json:"role"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type NotificationPreference struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
UserID pgtype.UUID `json:"user_id"`
Preferences []byte `json:"preferences"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type PersonalAccessToken struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
Name string `json:"name"`
TokenHash string `json:"token_hash"`
TokenPrefix string `json:"token_prefix"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
LastUsedAt pgtype.Timestamptz `json:"last_used_at"`
Revoked bool `json:"revoked"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type PinnedItem struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
UserID pgtype.UUID `json:"user_id"`
ItemType string `json:"item_type"`
ItemID pgtype.UUID `json:"item_id"`
Position float64 `json:"position"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type Project struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Title string `json:"title"`
Description pgtype.Text `json:"description"`
Icon pgtype.Text `json:"icon"`
Status string `json:"status"`
LeadType pgtype.Text `json:"lead_type"`
LeadID pgtype.UUID `json:"lead_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Priority string `json:"priority"`
}
type ProjectResource struct {
ID pgtype.UUID `json:"id"`
ProjectID pgtype.UUID `json:"project_id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
ResourceType string `json:"resource_type"`
ResourceRef []byte `json:"resource_ref"`
Label pgtype.Text `json:"label"`
Position int32 `json:"position"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
CreatedBy pgtype.UUID `json:"created_by"`
}
type Skill struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
Description string `json:"description"`
Content string `json:"content"`
Config []byte `json:"config"`
CreatedBy pgtype.UUID `json:"created_by"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type SkillFile struct {
ID pgtype.UUID `json:"id"`
SkillID pgtype.UUID `json:"skill_id"`
Path string `json:"path"`
Content string `json:"content"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type Squad struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
Description string `json:"description"`
LeaderID pgtype.UUID `json:"leader_id"`
CreatorID pgtype.UUID `json:"creator_id"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ArchivedAt pgtype.Timestamptz `json:"archived_at"`
ArchivedBy pgtype.UUID `json:"archived_by"`
AvatarUrl pgtype.Text `json:"avatar_url"`
Instructions string `json:"instructions"`
}
type SquadMember struct {
ID pgtype.UUID `json:"id"`
SquadID pgtype.UUID `json:"squad_id"`
MemberType string `json:"member_type"`
MemberID pgtype.UUID `json:"member_id"`
Role string `json:"role"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type TaskMessage struct {
ID pgtype.UUID `json:"id"`
TaskID pgtype.UUID `json:"task_id"`
Seq int32 `json:"seq"`
Type string `json:"type"`
Tool pgtype.Text `json:"tool"`
Content pgtype.Text `json:"content"`
Input []byte `json:"input"`
Output pgtype.Text `json:"output"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type TaskUsage struct {
ID pgtype.UUID `json:"id"`
TaskID pgtype.UUID `json:"task_id"`
Provider string `json:"provider"`
Model string `json:"model"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"`
CacheWriteTokens int64 `json:"cache_write_tokens"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type TaskUsageDaily struct {
BucketDate pgtype.Date `json:"bucket_date"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
RuntimeID pgtype.UUID `json:"runtime_id"`
Provider string `json:"provider"`
Model string `json:"model"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"`
CacheWriteTokens int64 `json:"cache_write_tokens"`
EventCount int64 `json:"event_count"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type TaskUsageDailyDirty struct {
BucketDate pgtype.Date `json:"bucket_date"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
RuntimeID pgtype.UUID `json:"runtime_id"`
Provider string `json:"provider"`
Model string `json:"model"`
EnqueuedAt pgtype.Timestamptz `json:"enqueued_at"`
}
type TaskUsageDashboardDaily struct {
BucketDate pgtype.Date `json:"bucket_date"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
AgentID pgtype.UUID `json:"agent_id"`
ProjectID pgtype.UUID `json:"project_id"`
Model string `json:"model"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"`
CacheWriteTokens int64 `json:"cache_write_tokens"`
TaskCount int64 `json:"task_count"`
EventCount int64 `json:"event_count"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
}
type TaskUsageDashboardDirty struct {
BucketDate pgtype.Date `json:"bucket_date"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
AgentID pgtype.UUID `json:"agent_id"`
ProjectID pgtype.UUID `json:"project_id"`
Model string `json:"model"`
EnqueuedAt pgtype.Timestamptz `json:"enqueued_at"`
}
type TaskUsageDashboardRollupState struct {
ID int16 `json:"id"`
WatermarkAt pgtype.Timestamptz `json:"watermark_at"`
LastRunStartedAt pgtype.Timestamptz `json:"last_run_started_at"`
LastRunFinishedAt pgtype.Timestamptz `json:"last_run_finished_at"`
LastRunRows int64 `json:"last_run_rows"`
LastError pgtype.Text `json:"last_error"`
}
type TaskUsageRollupState struct {
ID int16 `json:"id"`
WatermarkAt pgtype.Timestamptz `json:"watermark_at"`
LastRunStartedAt pgtype.Timestamptz `json:"last_run_started_at"`
LastRunFinishedAt pgtype.Timestamptz `json:"last_run_finished_at"`
LastRunRows int64 `json:"last_run_rows"`
LastError pgtype.Text `json:"last_error"`
}
type User struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
AvatarUrl pgtype.Text `json:"avatar_url"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
OnboardedAt pgtype.Timestamptz `json:"onboarded_at"`
OnboardingQuestionnaire []byte `json:"onboarding_questionnaire"`
CloudWaitlistEmail pgtype.Text `json:"cloud_waitlist_email"`
CloudWaitlistReason pgtype.Text `json:"cloud_waitlist_reason"`
StarterContentState pgtype.Text `json:"starter_content_state"`
Language pgtype.Text `json:"language"`
}
type VerificationCode struct {
ID pgtype.UUID `json:"id"`
Email string `json:"email"`
Code string `json:"code"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
Used bool `json:"used"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
Attempts int32 `json:"attempts"`
}
type WebhookDelivery struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
AutopilotID pgtype.UUID `json:"autopilot_id"`
TriggerID pgtype.UUID `json:"trigger_id"`
Provider string `json:"provider"`
Event string `json:"event"`
DedupeKey pgtype.Text `json:"dedupe_key"`
DedupeSource pgtype.Text `json:"dedupe_source"`
SignatureStatus string `json:"signature_status"`
Status string `json:"status"`
AttemptCount int32 `json:"attempt_count"`
SelectedHeaders []byte `json:"selected_headers"`
ContentType pgtype.Text `json:"content_type"`
RawBody []byte `json:"raw_body"`
ResponseStatus pgtype.Int4 `json:"response_status"`
ResponseBody pgtype.Text `json:"response_body"`
AutopilotRunID pgtype.UUID `json:"autopilot_run_id"`
ReplayedFromDeliveryID pgtype.UUID `json:"replayed_from_delivery_id"`
Error pgtype.Text `json:"error"`
ReceivedAt pgtype.Timestamptz `json:"received_at"`
LastAttemptAt pgtype.Timestamptz `json:"last_attempt_at"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
}
type Workspace struct {
ID pgtype.UUID `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description pgtype.Text `json:"description"`
Settings []byte `json:"settings"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
Context pgtype.Text `json:"context"`
Repos []byte `json:"repos"`
IssuePrefix string `json:"issue_prefix"`
IssueCounter int32 `json:"issue_counter"`
}
type WorkspaceInvitation struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
InviterID pgtype.UUID `json:"inviter_id"`
InviteeEmail string `json:"invitee_email"`
InviteeUserID pgtype.UUID `json:"invitee_user_id"`
Role string `json:"role"`
Status string `json:"status"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
}