Fresh repository history for elektrine/tarakan-client hosted at https://git.elektrine.com/elektrine/tarakan-client.
344 lines
13 KiB
Go
344 lines
13 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Repository is the canonical repository identity returned by Tarakan. Client
|
|
// code must compare this identity with the local origin before running a task.
|
|
type Repository struct {
|
|
ID int64 `json:"id,omitempty"`
|
|
Host string `json:"host,omitempty"`
|
|
Owner string `json:"owner"`
|
|
Name string `json:"name"`
|
|
FullName string `json:"full_name,omitempty"`
|
|
CanonicalURL string `json:"canonical_url,omitempty"`
|
|
ParticipationMode string `json:"participation_mode,omitempty"`
|
|
PrimaryLanguage string `json:"primary_language,omitempty"`
|
|
StarsCount int64 `json:"stars_count,omitempty"`
|
|
RecordURL string `json:"record_url,omitempty"`
|
|
}
|
|
|
|
func (r Repository) Slug() string {
|
|
if r.FullName != "" {
|
|
return r.FullName
|
|
}
|
|
if r.Owner == "" || r.Name == "" {
|
|
return ""
|
|
}
|
|
return r.Owner + "/" + r.Name
|
|
}
|
|
|
|
// Actor is the minimal public contributor identity returned by Tarakan.
|
|
type Actor struct {
|
|
ID int64 `json:"id,omitempty"`
|
|
Handle string `json:"handle,omitempty"`
|
|
}
|
|
|
|
type Lease struct {
|
|
ClaimedAt string `json:"claimed_at,omitempty"`
|
|
ExpiresAt string `json:"expires_at,omitempty"`
|
|
Active bool `json:"active"`
|
|
}
|
|
|
|
type Contribution struct {
|
|
ID int64 `json:"id,omitempty"`
|
|
Version int64 `json:"version,omitempty"`
|
|
Provenance string `json:"provenance"`
|
|
Summary string `json:"summary"`
|
|
Evidence string `json:"evidence,omitempty"`
|
|
Contributor *Actor `json:"contributor,omitempty"`
|
|
SubmittedAt string `json:"submitted_at,omitempty"`
|
|
}
|
|
|
|
type ReviewDecision struct {
|
|
ID int64 `json:"id,omitempty"`
|
|
Action string `json:"action"`
|
|
Reason string `json:"reason,omitempty"`
|
|
Evidence string `json:"evidence,omitempty"`
|
|
Reviewer *Actor `json:"reviewer,omitempty"`
|
|
DecidedAt string `json:"decided_at,omitempty"`
|
|
}
|
|
|
|
// Task is one immutable, commit-pinned unit of collaborative security work.
|
|
// ContractValue is what is currently escrowed against a job's repository. It
|
|
// is the answer to "is anyone paying for this?" at the moment the operator
|
|
// decides where to spend tokens.
|
|
type ContractValue struct {
|
|
Cents int64 `json:"cents"`
|
|
Credits int64 `json:"credits"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
// Label renders the value for a queue listing, or "" when nothing is on offer.
|
|
func (c *ContractValue) Label() string {
|
|
if c == nil || c.Count == 0 {
|
|
return ""
|
|
}
|
|
switch {
|
|
case c.Cents > 0 && c.Credits > 0:
|
|
return fmt.Sprintf("$%d + %d credits", c.Cents/100, c.Credits)
|
|
case c.Cents > 0:
|
|
return fmt.Sprintf("$%d", c.Cents/100)
|
|
case c.Credits > 0:
|
|
return fmt.Sprintf("%d credits", c.Credits)
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
type Task struct {
|
|
ID int64 `json:"id"`
|
|
Repository Repository `json:"repository"`
|
|
Contract *ContractValue `json:"contract,omitempty"`
|
|
CommitSHA string `json:"commit_sha"`
|
|
CommitCommittedAt string `json:"commit_committed_at,omitempty"`
|
|
Kind string `json:"kind"`
|
|
Capability string `json:"capability"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
Status string `json:"status"`
|
|
Visibility string `json:"visibility,omitempty"`
|
|
Creator *Actor `json:"creator,omitempty"`
|
|
Claimant *Actor `json:"claimant,omitempty"`
|
|
Reviewer *Actor `json:"reviewer,omitempty"`
|
|
Lease *Lease `json:"lease,omitempty"`
|
|
Contribution *Contribution `json:"contribution,omitempty"`
|
|
Contributions []Contribution `json:"contributions,omitempty"`
|
|
Decisions []ReviewDecision `json:"decisions,omitempty"`
|
|
PublishedAt string `json:"published_at,omitempty"`
|
|
SubmittedAt string `json:"submitted_at,omitempty"`
|
|
ReviewedAt string `json:"reviewed_at,omitempty"`
|
|
InsertedAt string `json:"inserted_at,omitempty"`
|
|
UpdatedAt string `json:"updated_at,omitempty"`
|
|
CompletedAt string `json:"completed_at,omitempty"`
|
|
DisclosedAt string `json:"disclosed_at,omitempty"`
|
|
Discloser *Actor `json:"discloser,omitempty"`
|
|
SensitiveReviewed bool `json:"sensitive_data_reviewed,omitempty"`
|
|
TaskURL string `json:"task_url,omitempty"`
|
|
RequestURL string `json:"request_url,omitempty"`
|
|
LinkedReviewID *int64 `json:"linked_review_id,omitempty"`
|
|
LinkedReview *LinkedReview `json:"linked_review,omitempty"`
|
|
TargetReviewID *int64 `json:"target_review_id,omitempty"`
|
|
TargetReview *LinkedReview `json:"target_review,omitempty"`
|
|
}
|
|
|
|
// LinkedReview is the structured Review created when completing a Request with
|
|
// Tarakan Review/Scan Format document.
|
|
type LinkedReview struct {
|
|
ID int64 `json:"id"`
|
|
ReviewStatus string `json:"review_status,omitempty"`
|
|
Visibility string `json:"visibility,omitempty"`
|
|
FindingsCount int64 `json:"findings_count,omitempty"`
|
|
Provenance string `json:"provenance,omitempty"`
|
|
ReviewKind string `json:"review_kind,omitempty"`
|
|
Model string `json:"model,omitempty"`
|
|
PromptVersion string `json:"prompt_version,omitempty"`
|
|
CommitSHA string `json:"commit_sha,omitempty"`
|
|
SourceRequestID *int64 `json:"source_request_id,omitempty"`
|
|
Findings []Finding `json:"findings,omitempty"`
|
|
}
|
|
|
|
// Submission completes a Request. Prefer Document (Review Format) for
|
|
// finding-producing kinds so Tarakan records Findings; Evidence is legacy prose.
|
|
// For verify_findings with target_review_id, set Verdict + Notes (or Summary).
|
|
type Submission struct {
|
|
Provenance string `json:"provenance"`
|
|
Summary string `json:"summary,omitempty"`
|
|
Evidence string `json:"evidence,omitempty"`
|
|
Model string `json:"model,omitempty"`
|
|
PromptVersion string `json:"prompt_version,omitempty"`
|
|
Document *ScanDocument `json:"document,omitempty"`
|
|
Verdict string `json:"verdict,omitempty"`
|
|
Notes string `json:"notes,omitempty"`
|
|
}
|
|
|
|
type Completion = Submission
|
|
|
|
// QueueRepository is a repository in the review queue returned by
|
|
// GET /api/repositories. It is the work a scanning client picks up.
|
|
type QueueRepository struct {
|
|
Host string `json:"host"`
|
|
Owner string `json:"owner"`
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
DefaultBranch string `json:"default_branch,omitempty"`
|
|
PrimaryLanguage string `json:"primary_language,omitempty"`
|
|
StarsCount int64 `json:"stars_count,omitempty"`
|
|
ScanCount int64 `json:"scan_count"`
|
|
LastScannedAt string `json:"last_scanned_at,omitempty"`
|
|
RegisteredAt string `json:"registered_at,omitempty"`
|
|
RecordURL string `json:"record_url,omitempty"`
|
|
}
|
|
|
|
// QueueFilter narrows jobs and repository discovery (stars, language, kind).
|
|
type QueueFilter struct {
|
|
MinStars int
|
|
Language string
|
|
Kind string
|
|
}
|
|
|
|
func (f QueueFilter) Empty() bool {
|
|
return f.MinStars <= 0 && strings.TrimSpace(f.Language) == "" && strings.TrimSpace(f.Kind) == ""
|
|
}
|
|
|
|
func (f QueueFilter) Query() url.Values {
|
|
values := url.Values{}
|
|
if f.MinStars > 0 {
|
|
values.Set("min_stars", strconv.FormatInt(int64(f.MinStars), 10))
|
|
}
|
|
if lang := strings.TrimSpace(f.Language); lang != "" {
|
|
values.Set("language", lang)
|
|
}
|
|
if kind := strings.TrimSpace(f.Kind); kind != "" {
|
|
values.Set("kind", kind)
|
|
}
|
|
return values
|
|
}
|
|
|
|
func (r QueueRepository) Slug() string {
|
|
if r.Owner == "" || r.Name == "" {
|
|
return ""
|
|
}
|
|
return r.Owner + "/" + r.Name
|
|
}
|
|
|
|
// Finding is one issue inside a review, visible only when the caller is
|
|
// authorized to see restricted evidence.
|
|
type Finding struct {
|
|
PublicID string `json:"public_id,omitempty"`
|
|
CanonicalFindingID string `json:"canonical_finding_id,omitempty"`
|
|
Disposition string `json:"disposition,omitempty"`
|
|
File string `json:"file"`
|
|
LineStart int64 `json:"line_start,omitempty"`
|
|
LineEnd int64 `json:"line_end,omitempty"`
|
|
Severity string `json:"severity"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
// ScanConfirmation is a recorded verdict on a review.
|
|
type ScanConfirmation struct {
|
|
Verdict string `json:"verdict"`
|
|
Provenance string `json:"provenance"`
|
|
Verifier string `json:"verifier,omitempty"`
|
|
}
|
|
|
|
// Scan is one submitted review of a repository at an exact commit.
|
|
type Scan struct {
|
|
ID int64 `json:"id"`
|
|
CommitSHA string `json:"commit_sha"`
|
|
Provenance string `json:"provenance"`
|
|
ReviewKind string `json:"review_kind"`
|
|
Model string `json:"model,omitempty"`
|
|
PromptVersion string `json:"prompt_version,omitempty"`
|
|
RunID string `json:"run_id,omitempty"`
|
|
ReviewStatus string `json:"review_status"`
|
|
Visibility string `json:"visibility"`
|
|
Verified bool `json:"verified"`
|
|
FindingsCount int64 `json:"findings_count"`
|
|
DetailsVisible bool `json:"details_visible"`
|
|
Submitter string `json:"submitter,omitempty"`
|
|
Findings []Finding `json:"findings,omitempty"`
|
|
Confirmations []ScanConfirmation `json:"confirmations,omitempty"`
|
|
}
|
|
|
|
// ScanDocument is the Tarakan Scan Format v1 body of a review submission.
|
|
type ScanDocument struct {
|
|
Format int64 `json:"tarakan_scan_format"`
|
|
Findings []ScanFinding `json:"findings"`
|
|
}
|
|
|
|
// ScanFinding is one finding inside a submitted ScanDocument.
|
|
type ScanFinding struct {
|
|
File string `json:"file"`
|
|
LineStart int64 `json:"line_start,omitempty"`
|
|
LineEnd int64 `json:"line_end,omitempty"`
|
|
Severity string `json:"severity"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
Disposition string `json:"disposition,omitempty"`
|
|
ExistingFindingID string `json:"existing_finding_id,omitempty"`
|
|
}
|
|
|
|
// ScanSubmission is the request body for POST .../scans.
|
|
type ScanSubmission struct {
|
|
CommitSHA string `json:"commit_sha"`
|
|
Provenance string `json:"provenance"`
|
|
ReviewKind string `json:"review_kind"`
|
|
Model string `json:"model,omitempty"`
|
|
PromptVersion string `json:"prompt_version,omitempty"`
|
|
RunID string `json:"run_id,omitempty"`
|
|
Document ScanDocument `json:"document"`
|
|
}
|
|
|
|
// RepositoryMemory is the compact canonical issue index used only after an
|
|
// agent has completed a blind discovery pass.
|
|
type RepositoryMemory struct {
|
|
Repository string `json:"repository"`
|
|
TargetCommitSHA string `json:"target_commit_sha,omitempty"`
|
|
Findings []CanonicalFindingMemory `json:"findings"`
|
|
Suppressions Suppressions `json:"suppressions"`
|
|
}
|
|
|
|
// Suppressions are findings the record already judged non-bugs. Reporting one
|
|
// again costs the operator tokens for a verdict that is already settled, so
|
|
// they are handed to the agent as things not to spend the budget rediscovering.
|
|
type Suppressions struct {
|
|
Note string `json:"note"`
|
|
Repository []Suppression `json:"repository"`
|
|
Patterns []Suppression `json:"patterns"`
|
|
}
|
|
|
|
type Suppression struct {
|
|
PublicID string `json:"public_id,omitempty"`
|
|
Fingerprint string `json:"fingerprint,omitempty"`
|
|
PatternKey string `json:"pattern_key,omitempty"`
|
|
File string `json:"file_path,omitempty"`
|
|
LineStart int64 `json:"line_start,omitempty"`
|
|
Title string `json:"title"`
|
|
DisputesCount int64 `json:"disputes_count,omitempty"`
|
|
DisputedRepositories int64 `json:"disputed_repositories,omitempty"`
|
|
Scope string `json:"scope"`
|
|
}
|
|
|
|
// Total is how many settled non-bugs this scan does not have to rediscover.
|
|
func (s Suppressions) Total() int { return len(s.Repository) + len(s.Patterns) }
|
|
|
|
type CanonicalFindingMemory struct {
|
|
PublicID string `json:"public_id"`
|
|
Status string `json:"status"`
|
|
File string `json:"file_path"`
|
|
LineStart int64 `json:"line_start,omitempty"`
|
|
LineEnd int64 `json:"line_end,omitempty"`
|
|
Severity string `json:"severity"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
FirstSeenCommitSHA string `json:"first_seen_commit_sha"`
|
|
LastSeenCommitSHA string `json:"last_seen_commit_sha"`
|
|
SameCommit bool `json:"same_commit"`
|
|
DetectionsCount int64 `json:"detections_count"`
|
|
DistinctSubmittersCount int64 `json:"distinct_submitters_count"`
|
|
DistinctModelsCount int64 `json:"distinct_models_count"`
|
|
ConfirmationsCount int64 `json:"confirmations_count"`
|
|
DisputesCount int64 `json:"disputes_count"`
|
|
}
|
|
|
|
type FindingVerdict struct {
|
|
CommitSHA string `json:"commit_sha"`
|
|
Verdict string `json:"verdict"`
|
|
Provenance string `json:"provenance"`
|
|
Notes string `json:"notes"`
|
|
Evidence string `json:"evidence,omitempty"`
|
|
}
|
|
|
|
// Verdict is the request body for POST .../scans/:id/verdict.
|
|
type Verdict struct {
|
|
Verdict string `json:"verdict"`
|
|
Provenance string `json:"provenance"`
|
|
Notes string `json:"notes"`
|
|
Evidence string `json:"evidence,omitempty"`
|
|
}
|