Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board
HomeBy LayerGovernance6.10 ParameterChangeAuditor

6.10 ParameterChangeAuditor

Governance Governance Service Explain PLANNED Spec started capital · Indirect P7 · Governance & replay pending stub

ParameterChangeAuditor intercepts every config edit across the Polytraders fleet, records what changed, who changed it, when, and the before/after values with replay-grade detail.

v3 readiness

Docs27/27
donehow scored
Impl0/15
pendinghow scored
Backtest0/4
pendinghow scored
Runtime0/8
pendinghow scored

A bot is done when all four scores are. What does done mean?

1. Bot Identity

LayerGovernance  Governance
Bot classGovernance Service
AuthorityExplain
StatusPLANNED
ReadinessSpec started
Runs beforeAny bot whose parameters change — audit hook fires pre-write
Runs afterEvery parameter update across the Polytraders bot fleet
Applies toEvery bot parameter in the system
Default modeshadow_only
User-visibleno
Developer ownerPolytraders core

2. Purpose

ParameterChangeAuditor intercepts every config edit across the Polytraders fleet, records what changed, who changed it, when, and the before/after values with replay-grade detail.

3. Why This Bot Matters

  • Parameter change not recorded

    Incidents cannot be root-caused; audit trails are incomplete for compliance.

  • P0 parameter changed without alert

    A high-risk config change may go unnoticed until it causes a trading incident.

No worked examples on this bot yet. Worked examples are optional but strongly recommended — they turn an abstract failure mode into something a developer can verify in a fixture.

4. Required Polymarket Inputs

InputSourceRequired?Use
None — pure internal config audit hookinternalNoN/A

5. Required Internal Inputs

InputSourceRequired?Use
Pre-write config delta event from each bot's config storeinternalYesCapture before/after parameter values and editor identity.
Ticket reference from change management systeminternalNoLink the change to an approved ticket if require_ticket_for applies.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
retain_history_days365180365How many days of parameter change history to retain.
alert_on_p0_changeTrueNoneNoneWhen true, any change to a P0-tagged parameter triggers an immediate alert.

7. Detailed Parameter Instructions

retain_history_days

What it means

How many days of parameter change history to retain.

Default

{ "retain_history_days": 365 }

Why this default matters

365 days covers a full trading year for audit purposes.

Threshold logic

ConditionAction
retain_history_days >= 365Retain; normal operation

Developer check

if p.retain_history_days < 90: emit('AUDIT_RETENTION_WARN')

User-facing English

Config changes are kept on record for one year.

alert_on_p0_change

What it means

When true, any change to a P0-tagged parameter triggers an immediate alert.

Default

{ "alert_on_p0_change": true }

Why this default matters

P0 parameters are risk-critical; immediate alerting is mandatory.

Threshold logic

ConditionAction
p0_change AND alert_on_p0_change=trueEmit P0_PARAMETER_CHANGED alert immediately

Developer check

if param.tier == 'P0': alerting.emit('P0_PARAMETER_CHANGED')

User-facing English

— not yet authored —

8. Default Configuration

{
  "bot_id": "gov.parameterchangeauditor",
  "version": "0.1.0",
  "mode": "shadow_only",
  "defaults": {
    "retain_history_days": 365,
    "require_ticket_for": [
      "P0",
      "P1"
    ],
    "publish_to_audit_log": true,
    "alert_on_p0_change": true
  }
}

9. Implementation Flow

  1. Hook into the config store write path of every bot; intercept before-write events.
  2. Compute diff between old and new parameter values.
  3. Record: bot_slug, param_name, old_value, new_value, editor_id, environment, timestamp, ticket_ref.
  4. If param tier is in require_ticket_for and ticket_ref is absent, reject the change and emit AUDIT_TICKET_REQUIRED.
  5. If alert_on_p0_change and param tier is P0, emit P0_PARAMETER_CHANGED alert immediately.
  6. Emit OperationsReport(event_type=PARAM_CHANGED) to audit log.
  7. Enforce retain_history_days; purge records older than retention window.

10. Reference Implementation

Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. IF/THEN/ELSE = decision. Translate directly to TypeScript, Python, Go, or Rust.

// ---- PRE-WRITE HOOK ----
FUNCTION onConfigWrite(botSlug, paramName, oldVal, newVal, editorId, ticketRef):
  tier = paramTierMap.get(botSlug + '.' + paramName, 'P2')
  IF tier IN config.require_ticket_for AND ticketRef IS NULL:
    EMIT OperationsReport(event_type='AUDIT_TICKET_REQUIRED',
      audited_bot=botSlug, param_name=paramName)
    RAISE ConfigError('AUDIT_TICKET_REQUIRED')
  record = {
    audited_bot: botSlug, param_name: paramName,
    old_value: oldVal, new_value: newVal,
    editor_id: editorId, ticket_ref: ticketRef,
    param_tier: tier, changed_at: now()
  }
  IF auditLog.available():
    postgres.insert('param_change_audit', record)
  ELSE:
    memBuffer.append(record)
    alerting.emit('AUDIT_LOG_UNAVAILABLE')
  IF tier == 'P0' AND config.alert_on_p0_change:
    alerting.emit('P0_PARAMETER_CHANGED', record)
  EMIT OperationsReport(event_type='PARAM_CHANGED', ...record)

// ---- RETENTION PURGE (scheduled) ----
FUNCTION purgeOldRecords():
  cutoff = now() - days(config.retain_history_days)
  postgres.deleteWhere('param_change_audit', changed_at < cutoff)

SDK calls used

  • postgres.insert('param_change_audit', record)
  • postgres.deleteWhere('param_change_audit', cutoff)
  • alerting.emit('P0_PARAMETER_CHANGED', record)

Complexity: O(1) per config write; O(N) for retention purge where N = records older than cutoff

11. Wire Examples

Input — what arrives on the wire

{
  "label": "Config write event",
  "source": "internal.config_store",
  "payload": {
    "bot_slug": "risk.liquidityguard",
    "param_name": "max_position_pusd",
    "old_value": 5000,
    "new_value": 7500,
    "editor_id": "alice@polytraders",
    "ticket_ref": "PTRD-1042"
  }
}

Output — what the bot emits

{
  "label": "OperationsReport — PARAM_CHANGED",
  "payload": {
    "report_id": "ops_paramchange_01HX9Z",
    "event_type": "PARAM_CHANGED",
    "audited_bot": "risk.liquidityguard",
    "param_name": "max_position_pusd",
    "old_value": 5000,
    "new_value": 7500,
    "report_kind": "OperationsReport"
  }
}

12. Decision Logic

APPROVE

Not applicable — ParameterChangeAuditor does not approve changes; it records them.

RESHAPE_REQUIRED

Not applicable.

REJECT

Rejects changes to P0/P1 parameters missing a ticket reference.

WARNING_ONLY

Emits AUDIT_RETENTION_WARN if retain_history_days < 90.

13. Standard Decision Output

This bot returns a OperationsReport object. See OperationsReport schema.

{
  "report_id": "ops_paramchangeauditor_01HX9Z",
  "bot_id": "gov.parameterchangeauditor",
  "event_type": "PARAM_CHANGED",
  "audited_bot": "risk.liquidityguard",
  "param_name": "max_position_pusd",
  "old_value": 5000,
  "new_value": 7500,
  "editor_id": "alice@polytraders",
  "ticket_ref": "PTRD-1042",
  "param_tier": "P1",
  "changed_at": "2026-05-09T10:00:00Z",
  "report_kind": "OperationsReport",
  "topic": "polytraders.reports.operations"
}

14. Reason Codes

CodeSeverityMeaningActionUser-facing message
PARAM_CHANGEDINFOA parameter was successfully changed and recorded.Log and emit OperationsReport.
P0_PARAMETER_CHANGEDWARNA P0-tier parameter was changed; immediate alert required.Emit alert to on-call.
AUDIT_TICKET_REQUIREDHARD_REJECTA P0/P1 parameter change was attempted without a ticket reference.Reject change; emit alert.
AUDIT_LOG_UNAVAILABLEWARNAudit log store is unavailable; records buffered in memory.Buffer and flush on reconnect.
AUDIT_RETENTION_WARNWARNretain_history_days < 90; below recommended minimum.Emit WARN.

15. Metrics & Logs

Metrics emitted

MetricTypeUnitLabelsMeaning
polytraders_gov_parameterchangeauditor_changes_totalcountercountbot_slug, param_tierTotal parameter changes recorded.
polytraders_gov_parameterchangeauditor_rejections_totalcountercountreasonTotal changes rejected by audit hook.
polytraders_gov_parameterchangeauditor_p0_alerts_totalcountercountTotal P0 parameter change alerts fired.
polytraders_gov_parameterchangeauditor_buffer_sizegaugecountRecords buffered in memory awaiting audit log flush.

Alerts

AlertConditionSeverityRunbook
ParameterAuditorP0Changerate(polytraders_gov_parameterchangeauditor_p0_alerts_total[5m]) > 0P1#runbook-parameterauditor-p0
ParameterAuditorLogUnavailablepolytraders_gov_parameterchangeauditor_buffer_size > 100P1#runbook-parameterauditor-log

16. Developer Reporting

{
  "bot_id": "gov.parameterchangeauditor",
  "event_type": "AUDIT_HOOK_FIRED",
  "audited_bot": "risk.liquidityguard",
  "param_name": "max_position_pusd",
  "diff": {
    "old": 5000,
    "new": 7500
  }
}

17. Plain-English Reporting

SituationUser-facing explanation
Parameter change recordedA configuration change was recorded in the audit log with full before/after detail.
Change rejected — missing ticketThis parameter requires an approved change ticket before it can be modified.

18. Failure-Mode Block

main_failure_modeAudit log store is unavailable; changes are written to the bot's config but not recorded in the audit trail.
false_positive_riskA benign automated parameter update (e.g. TTL refresh) is flagged as a P0 change.
false_negative_riskA config change bypasses the hook if applied directly to the underlying store.
safe_fallbackIf audit log is unavailable, buffer the audit record in memory and flush on reconnect; never block the config write.
required_dependenciesInternal audit log store (Postgres), Config store write hooks for all bots

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
AUDIT_LOG_UNAVAILABLEKill Postgres connection during a parameter changeBuffer flushed when Postgres reconnects.
P0_CHANGE_WITHOUT_TICKETSubmit P0 parameter change with ticket_ref=nullResubmit with valid ticket reference.
BUFFER_OVERFLOWKeep Postgres down for 10 minutes; submit 200 changesRestore Postgres; buffer flushes automatically.

20. State & Persistence

Cold-start recovery

On restart, flush memory buffer to Postgres; no in-memory state required.

21. Concurrency & Idempotency

AspectSpecification
Execution modelsynchronous pre-write hook; single-threaded per bot config store
Max in-flight50
Idempotency keyaudited_bot + param_name + changed_at
Per-call timeout (ms)500
Backpressure strategybuffer-in-memory
Locking / mutual exclusionnone (audit writes are append-only)

22. Dependencies

Depends on (must run first)

BotWhyContract
internal.config_storeConfig store fires pre-write events to the audit hook.Every config write must trigger the hook.

Emits to (downstream consumers)

BotWhyContract
internal.governance_audit

Sibling bots (same OrderIntent)

BotWhyContract
gov.incidentcommanderIncidentCommander queries recent parameter changes during RCA.OperationsReport records are queryable by audited_bot and changed_at.

External services

ServiceEndpointSLA assumedOn failure
Internal Postgres (audit log)postgres://internal99.9%Buffer in memory; flush on reconnect; never block config writes.

23. Security Surfaces

Abuse vectors considered

  • Direct database write to bypass the audit hook
  • Providing a fake ticket reference for a P0 change

Mitigations

  • Config store enforces hook invocation; direct DB writes are blocked by access controls
  • Ticket references are validated against the change management system

24. Polymarket V2 Compatibility

AspectValue
CLOB versionv2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldno
Aware of negative-risk marketsno
Multi-chain readyno
SDK usedpy-clob-client-v2
Settlement contractCTFExchangeV2
NotesParameterChangeAuditor is an internal config audit service; pUSD references appear only in logged parameter values for strategies.

API surfaces declared

internal

Networks supported

polygon

25. Versioning & Migration

FieldValue
spec2.0.0
implementation0.1.0
schema2
releasedNone
planned_releaseQ3-2026

Migration history

DateFromToReasonAction taken
2026-04-28n/av2-specSpec drafted post-CLOB-V2 cutover; bot not yet implementedDesigned against V2 schema (pUSD, builder codes, V2 EIP-712 domain)

26. Acceptance Tests

Unit Tests

TestSetupExpected result
P1 change without ticket reference is rejectedparam_tier=P1, ticket_ref=nullAUDIT_TICKET_REQUIRED; change rejected
P0 change triggers immediate alertparam_tier=P0, alert_on_p0_change=trueP0_PARAMETER_CHANGED alert emitted

Integration Tests

TestExpected result
End-to-end: config change → audit hook → OperationsReport on audit logOperationsReport with event_type=PARAM_CHANGED and full diff

Property Tests

PropertyRequired behaviour
Every config write fires the audit hook before the write completesAlways true — hook is synchronous pre-write

27. Operational Runbook

ParameterChangeAuditor incidents are usually audit log unavailability or P0 parameter alerts.

On-call actions

AlertFirst stepDiagnosisMitigationEscalate to
ParameterAuditorP0Change
ParameterAuditorLogUnavailable

Manual overrides

Healthcheck

/internal/health/parameterchangeauditor → green if Postgres reachable; buffer_size == 0; last change recorded < 1h ago; red if buffer_size > 100 or Postgres unreachable

28. Promotion Gates

A bot does not advance to the next readiness state until every gate below is green. Gates are observable from production data — no subjective sign-off.

Promote to Shadow

GateHow measuredThreshold
Pre-write hook unit tests pass for all tier levelsCI100% pass

Promote to Limited live

GateHow measuredThreshold
Audit log write integration test passesIntegration testPass

Promote to General live

GateHow measuredThreshold
P0 alert fires within 1s of P0 parameter change in stagingAlert latency test< 1s

29. Developer Checklist

Ready-to-ship score: 27/27 sections complete · 100%

RequirementStatus
Purpose defined✓ done
Required inputs listed✓ done
Parameters defined✓ done
Defaults defined✓ done
Warning thresholds defined✓ done
Hard thresholds defined✓ done
Safe fallback defined✓ done
Structured output defined✓ done
Developer log defined✓ done
Plain-English explanation✓ done
Unit tests defined✓ done
Integration tests defined✓ done
Property tests defined✓ done
Failure-mode block complete✓ done
Reference implementation pseudocode✓ done
Wire examples (input + output)✓ done
Reason codes listed✓ done
Metrics & logs defined✓ done
State & persistence defined✓ done
Concurrency & idempotency defined✓ done
Dependencies declared✓ done
Security surfaces declared✓ done
Polymarket V2 compatibility declared✓ done
Version & migration history declared✓ done
Operational runbook defined✓ done
Promotion gates defined✓ done
Failure-injection recipes defined✓ done