Skip to content

docs(api): daily audit 2026-10-09 — drop the reverted incident_list panel kind, add the resolve and feed assignee fields - #1032

Merged
ysyneu merged 2 commits into
mainfrom
api-review/20261009T080857Z
Oct 9, 2026
Merged

ysyneu merged 2 commits into
mainfrom
api-review/20261009T080857Z

Conversation

@flashduty

@flashduty flashduty Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Daily API-reference audit — 2026-10-09

Scope: --mode generate --scope all --auto. Round drawn against flashduty-docs main = 35773ebf. Branch api-review/20261009T080857Z.

Window analysis

Window start = the previous run (2026-10-08T08:00:17Z, the round that produced #1023). Each source repo was base-diffed from the last commit before that instant to origin/main, so commits merged in-window with older author dates are not missed:

repo window base origin/main changed files (excl. tests/docs)
monit-webapi 75bf6c5 9997944 types/dashboard/{contract,validate,variants,runtime}.go, logic/{dashboard_runtime_template,logic_dashboard_runtime,logic_dashboard,logic_explore}.go
fc-event 94bc9a6 8bccb5e78 structs/{feed,change,severity,work_item}.go, logic/{transfer,insight/incident,post_incident/*}.go, cmd/server/controller/{insight,post_incident,resource}/*
fc-rum 0943fb2 065c93f cmd/engine/controller/event/event.go, logic/sourcemap/*
fc-pgy 1226e6b 95c75610 42 files — regenerated registry, logic/idp/*, logic/charge/* (all non-public auth)
fc-oncall / fc-statuspage / fc-datasource / go-pkg — unchanged none

Operation changes per module

module added updated removed
on-call 0 0 0
monitors 0 0 0
rum 0 0 0
platform 0 0 0
safari 0 0 0

No operation was added, removed, or re-versioned. The fc-pgy registry is unchanged at 366 auth: "all" rows (row-level diff against the window base 1226e6b: 0 added, 0 removed, 0 auth flips), and the committed spec still holds 365 public operations — the one-row gap is fully accounted for below. No auth flip. The only registry auth: "all" rows with no matching spec operation are two, both known: POST /channel/incident/daily-counts (no handler, 6th consecutive round) and GET /monit/prometheus/api/v1/label/:label_name/values, which is the gin :param spelling of the spec's {label_name} — same operation, not a gap.

New non-public registry rows added this window (GET /safari/oauth/client-metadata.json auth: none, POST /oauth/client/describe auth: jwt, GET /.well-known/oauth-authorization-server auth: none) are correctly skipped.

Because there is no page add/delete, docs.json and both {en,zh}/openapi/api-catalog.mdx are deliberately untouched, and api-reference/openapi.legacy.zh.json is untouched.

What changed

1. incident_list is gone — the panel kind was reverted upstream (5 leaves × 4 files).

monit-webapi 5ee1fec (2026-10-08 04:38 −0700) reverts PR #135 feat/dashboard-incident-list-panel; the revert was merged by PR #151 (b0053a5, 04:47 −0700). Both land after the previous run's window, which is why #1023 documented the kind and this round has to take it back out. Current origin/main evidence:

  • types/dashboard/contract.go — QuerylessVizKind() deleted (git grep incident_list origin/main -- '*.go' returns nothing).
  • types/dashboard/variants.go — VizConfig.UnmarshalJSON case "incident_list" deleted.
  • types/dashboard/validate.go:475 — back to case "text":, with the message hard-coded to "text requires no queries" / "text cannot have a datasource".

Reverted in the specs:

  • delete schema DashboardIncidentListViz (monitors split 185 → 184 schemas; consolidated 826 → 825);
  • drop the DashboardIncidentListViz arm from DashboardVizConfig.oneOf and the incident_list key from discriminator.mapping;
  • drop incident_list from the DashboardOutlineVizConfig.kind enum and from its | value | meaning |-style description;
  • DashboardPanel.queries description goes back to "text accepts none" (「text 不允许查询」).

2. POST /monit/dashboard/runtime/queries/resolve gained two request fields.

monit-webapi types/dashboard/runtime.go — QueriesResolveInput at types/dashboard/runtime.go:66,68 (merged via ab51490 / PR #155 and 338f44b / PR #156, both in-window) now has:

MaxDataPoints *int64 `json:"max_data_points,omitempty"`        // validated 2..5000
PreserveBuiltinVariables bool `json:"preserve_builtin_variables,omitempty"`

DashboardQueriesResolveRequest therefore gains max_data_points (type: ["integer","null"], minimum: 2, maximum: 5000 — the pointer scalar rule from generate.md Step 3, bounds from MinMaxDataPoints/MaxMaxDataPoints at types/dashboard/runtime.go:17-18) and preserve_builtin_variables (type: boolean, a value bool so it stays non-nullable). Inserted after variables, matching the Go struct order in the split files and the file's own existing order in the consolidated copies.

3. The feed detail for work items carries structured assignees.

fc-event 7eff20f30 feat(work-item): let AI SRE be an assignee (author date 2026-09-23) reached main this window via PR #2456 (8bccb5e78), which is why earlier rounds could not act on it and this one can. structs/feed.go:

  • FDetailWorkItemCreated gains Assignees []WorkItemAssigneeRef \json:"assignees,omitempty"``;
  • FDetailWorkItemAssigneesChanged gains Assignees, AddedAssignees, RemovedAssignees.

Declared at structs/feed.go:427 and :449; populated at logic/post_incident/work_item.go:318 and :543; added_assignee_ids / removed_assignee_ids are computed by personAssigneeIDs() (logic/post_incident/work_item_validate.go:178), which skips ai_sre and non-positive ids — hence the "person-only subset" wording. All three fields are omitempty, so the descriptions say "omitted when empty" rather than the "never null" wording used by WorkItemItem.assignees (which has no omitempty).

4. Two input-validation rules the API now enforces.

  • monit-webapi types/dashboard/validate.go:270 — a dashboard variable name starting with __ is rejected (reserved): added to the name description of DashboardCustomVariable, DashboardDatasourceVariable, DashboardQueryVariable.
  • monit-webapi types/dashboard/validate.go:429-439 — for a Loki variable query an empty expr is now accepted (it lists the field's values across all streams), field must match ^[A-Za-z_][A-Za-z0-9_]*$ (a bare stream label), and args must be empty. Added to DashboardLogsVariableQuery.{expr,args,field}.

5. Committed split↔consolidated drift, resolved from the Go source (rule 7).

A full sort-key comparison of every schema shared between a split file and the consolidated copy found exactly two content drifts besides the known DutyError.reason item, and in both the split side was the stale one:

  • WorkItemItem.required — the split files listed 12 fields, the consolidated 13. fc-event structs/work_item.go declares Assignees []WorkItemAssigneeRef \json:"assignees"`**without**omitempty, so it is always serialized and belongs in required(itsomitemptysiblingspost_mortem_id, description, priority, legacy_source_id, converted_by, converted_at_seconds, agent_session_id, agent_session_venueare all correctly absent).assigneesadded at index 8, afterassignee_ids`.
  • ListWorkItemRequest.description — the split described three anchors, the consolidated four. fc-event logic/post_incident/work_item.go:942 rejects the call with the literal message "incident_id, post_mortem_id, assignee_id, or assignee_type=ai_sre is required", and workItemAssigneeFilter (model/post_incident/work_item.go) treats assignee_type=ai_sre as a standalone scope. The split description now carries the fourth anchor.

Per the direction rule, these were judged against the Go source, not against which file "wins" by role; the consolidated copy happened to be right both times. The remaining split↔consolidated difference is DutyError.reason in on-call/rum/safari/platform, which carries the deliberate x-flashduty-preserve-absence marker — left alone and reported under unresolved, as in previous rounds.

Verification performed

  • Every written file parses: python3 -c "import json; json.load(open(path))" — monitors 41 paths / 184 schemas, on-call 202 / 410, consolidated 365 / 825.
  • python3 scripts/lint_openapi.py → OK: 12 spec files, no violations (the same gate CI runs on api-reference/*.json).
  • Leaf-level deep compare against the round base (git show 35773ebf:<path>, i.e. the committed baseline only, never the worktree): 172 changed leaves in total, every one itemised above — monitors.openapi.* 7 added / 13 removed / 8 changed, on-call.openapi.* 12 added / 0 / 0 plus the 4 required-shift + 1 description leaf from section 5, consolidated 19 / 13 / 8. No reorder-only leaf.
  • git diff --numstat equals git diff --numstat --minimal for all six files (23/37, 23/37, 30/1, 30/1, 51/37, 51/37), i.e. no phantom delete/re-add despite the schema removal.
  • Byte round-trip: each file is reproduced exactly by json.dumps(obj, ensure_ascii=False, indent=2) + "\n" (trailing newline probed per file).
  • EN/ZH structural parity with human-text keys masked (summary, description, title, x-mint, tags, name, x-enumDescriptions, examples): 0 differences across all five modules and the consolidated pair. operationId/path/schema names/$refs are untouched.
  • Request/response example values byte-identical EN↔ZH: 0 differences. No operation was added, so no new example had to be constructed this round.
  • Nav + catalog reachability (Step 5.5 check, since mint is unavailable): on-call 202, monitors 41, rum 41, safari 53, platform 28 — every path found in docs.json and in both api-catalog.mdx, 0 missing in all three surfaces.
  • on-call split↔consolidated re-scanned after section 5: only DutyError remains (see unresolved).
  • Epoch wording: EN↔ZH cross-table over all 719 int64 format fields — the only "EN has a keyword / ZH does not" hits are the 12 short-form fields (AlertInfo/IncidentInfo/IncidentFeedItem/WarRoomItem *_at), whose ZH text uses 时间戳; scripts/lint_openapi.py's EPOCH_RE accepts 时间戳, and the lint passes. Not drift.
  • Diff size: +208 / −150 across 6 files (two commits: the audit, then the drift alignment). This exceeds the "under 100 lines when no operation is added" heuristic because the round is dominated by a schema deletion (25 lines) rather than a text tweak; every line is enumerated above.

Unresolved / deferred

  • POST /channel/incident/daily-counts — registry Auth: "all", no handler found in any repo. 6th consecutive round. Not emitted.
  • DutyError.reason split/consolidated inconsistency (x-flashduty-preserve-absence present in monitors split + both consolidated files, absent from the other four splits). Deliberate human marker vs references/response-envelope.md's two-field DutyError — human arbitration, untouched.
  • {{ }} template wording in the monitors module is inaccurate and was not touched this round: monit-webapi only supports ${name} (types/dashboard/validate.go:1295 — "only ${name} templates are supported") plus, since this window, bare $name for Prometheus/Loki. 10 occurrences per file in monitors.openapi.{en,zh}.json and both consolidated files describe the syntax as {{ }} and speak of "event labels". This predates the window, so changing it would have tripled the diff; it deserves its own pass.
  • The built-in time variables themselves ($__auto, $__interval, $__rate_interval, $__range, availability per datasource × mode in types/dashboard/validate.go:1180-1200) are a new capability of the public panel-query endpoints but are not yet documented anywhere in the spec. Candidate for an x-mint.content usage section on /monit/dashboard/panel/run rather than a field description.
  • mint broken-links could not be run — no node/npx in this environment. Substituted the Step 5.5 reachability check above.
  • Pre-existing (not a window change, not touched): consolidated DutyError.reason carries x-flashduty-preserve-absence in monitors/rum only, contradicting references/response-envelope.md (which requires exactly code + message); left to human arbitration as in previous rounds.

Automated notes

  • Examples: none constructed this round (no new operations); no dev-API capture was possible in this environment (FLASHDUTY_APP_KEY is not reachable from the agent's shell), which was not needed.
  • Registry/source repos were read from origin/main of flashcatcloud/<repo> only; the fc-pgy registry parser was run against logic/api/api_test.go at both the window base and origin/main for the row-level diff.

flashduty-bot added 2 commits October 9, 2026 08:08
…anel kind, add the resolve and feed assignee fields
…work-item assignees required, list anchor)
@ysyneu
ysyneu merged commit 4da828e into main Oct 9, 2026
2 checks passed
@ysyneu
ysyneu deleted the api-review/20261009T080857Z branch October 9, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant