Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,11 @@ computations, with no cloud, storage, egress, or recurring-service cost.
`sith audit verify-pages <page.json> [page.json...]` performs the same strict bounded-file and
canonical-hash checks one page at a time, then requires one ordered same-workspace,
same-snapshot genesis-to-head sequence with no missing, replayed, or swapped page. Success is still
internal consistency, not external authenticity. Paging adds one small audit row, at most 512
entry reads plus fixed anchors, and one response of egress per page; work is linear in retained
entries and page count, with no object store, queue, worker, or recurring cloud resource.
internal consistency, not external authenticity. The online page route adds one small audit row,
at most 512 entry reads plus fixed anchors, and one bounded response of egress per page. Offline
`verify-pages` instead performs one bounded local read and bounded local SHA-256 verification over
at most 512 entries per page, with no hub request or network egress. Both paths are linear in
retained entries and page count and add no object store, queue, worker, or recurring cloud resource.

Responses use `X-Content-Type-Options: nosniff` and the fixed `sith-policy-audit.json` or
`sith-policy-audit-page.json` attachment filename. Authentication is bearer-only; neither route
Expand Down Expand Up @@ -469,10 +471,11 @@ after a ten-minute hold. `deny` and `require-approval` remain valid decisions in
not failures. This is a fail-closed PEP symptom, not an external Ardur PDP-latency SLI or SLO.
At least twenty aggregate `refused` authentication attempts with zero `accepted` attempts over
fifteen minutes, sustained for ten minutes, produce one aggregate warning. Any accepted attempt in
the same window suppresses it. At least one accepted-outcome sample must also have reached the rule
evaluator during the last ten minutes; a missing or stale accepted series stays quiet rather than
turning partial telemetry into a refusal-only claim. This is not proof of brute force, credential
stuffing, account compromise, a specific actor, or a negotiated authentication SLO.
the same window suppresses it. At least one recent scraped sample from the preinitialized
accepted-outcome series must also have reached the rule evaluator during the last ten minutes; this
proves series visibility, not an accepted event. A missing or stale accepted series stays quiet
rather than turning partial telemetry into a refusal-only claim. This is not proof of brute force,
credential stuffing, account compromise, a specific actor, or a negotiated authentication SLO.
Chain verification detects retained-row edits,
deletion, reordering, broken links, and head mismatch. It does not make a WORM or non-repudiation
claim: detecting wholesale replacement by a privileged database owner requires a later externally
Expand Down
12 changes: 9 additions & 3 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ erDiagram
string approver
string resolved_digest "args + resolved target"
timestamp approved_at
timestamp expires_at "DB-derived approved_at + 10 minutes"
timestamp consumed_at "nullable, set once"
}
MEMBERSHIP {
Expand All @@ -357,9 +358,14 @@ Design points:
broaden access through PostgreSQL's OR-composition rule.
- **`DECISION` (why-allowed, Ardur) and `AUDITLOG` (what-happened, Sith) are separate**
and together form a complete agent-action ledger.
- **`APPROVAL` is mutable in exactly one direction** — its identity and resolved digest are
immutable, while one atomic `consumed_at IS NULL` update spends it. FORCE RLS isolates the row;
the application role cannot delete it or update any other column.
- **`APPROVAL` is mutable in exactly one direction** — its identity, resolved digest,
`approved_at`, and `expires_at` are immutable. PostgreSQL derives
`expires_at = approved_at + interval '10 minutes'`; callers cannot supply it, and a database
constraint plus column privileges reject later drift. One atomic update spends the row only when
`consumed_at IS NULL` and `approved_at <= statement_timestamp() < expires_at`. Missing,
mismatched, future, expired, or already-consumed grants affect no row and return the same stable
unavailable refusal. FORCE RLS isolates the row; the application role cannot delete it or update
any other column.
- **`CLUSTER.last_seen` / `FLEET_FACT.observed_at`** are what abstention reads.

## 6. Enforcement pipeline (the PEP)
Expand Down
8 changes: 5 additions & 3 deletions docs/EPICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2741,9 +2741,11 @@ budget, a page, or a dispatch-success signal.
**Implementation note (F10.4g).** A ninth portable warning consumes only the bounded
`sith_auth_attempts_total{outcome="accepted|refused"}` counter. It fires when at least twenty
aggregate attempts are `refused` and none are `accepted` over fifteen minutes, and the condition
persists for ten minutes. Any accepted attempt suppresses it, and at least one accepted-outcome
sample must have reached the evaluator during the most recent ten minutes. Missing or stale
accepted-series data stays quiet rather than turning incomplete telemetry into a security claim.
persists for ten minutes. Any accepted attempt suppresses it. The freshness guard also requires at
least one recent scraped sample from the preinitialized accepted-outcome series during the most
recent ten minutes; that proves series visibility, not an accepted authentication event. Missing or
stale accepted-series data stays quiet rather than turning incomplete telemetry into a security
claim.
The expression aggregates away every source label and emits one fixed warning. It is refusal-only
traffic, not a generic refusal ratio, brute-force or credential-stuffing detector, actor
attribution, SLO, error budget, page, or complete authentication-monitoring claim, and it adds no
Expand Down
6 changes: 4 additions & 2 deletions docs/adr/0012-opencost-coverage-aware-workspace-rollup.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ workload or arbitrary label would create unstable cross-tenant accounting semant
reported. With no report, `observed_at` is absent. No collection time or stale objective is
invented.
8. The computation is bounded to 256 scopes, 1,024 facts per scope, 4,096 facts total, 8 MiB of
normalized payload, a 256 KiB result, and an aggregate magnitude derived from the per-fact cost
bound.
normalized payload, and a 256 KiB result. Each of the fifteen cost fields is accumulated and
checked independently: one fact's absolute field value cannot exceed `1,000,000,000,000`, and
one rollup's absolute field total cannot exceed `4,096,000,000,000,000` (the per-fact limit
multiplied by the 4,096-fact limit).

## Consequences

Expand Down
15 changes: 9 additions & 6 deletions docs/runbooks/hub-alerts.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,12 @@ degraded.

**Meaning.** At least 20 aggregate completed authentication attempts were `refused` and none were
`accepted` over 15 minutes, and that condition persisted for 10 minutes. Any accepted attempt in
the same window suppresses the warning. At least one accepted-outcome sample must have reached the
evaluator during the last 10 minutes. The rule stays quiet when that series is absent or stale,
because partial telemetry cannot prove refusal-only traffic. This is an operational symptom, not
proof of brute force, credential stuffing, account compromise, or a specific actor.
the same window suppresses the warning. At least one recent scraped sample from the preinitialized
accepted-outcome series must have reached the evaluator during the last 10 minutes. That sample
proves series visibility, not an accepted authentication event. The rule stays quiet when that
series is absent or stale, because partial telemetry cannot prove refusal-only traffic. This is an
operational symptom, not proof of brute force, credential stuffing, account compromise, or a
specific actor.

**Triage.**

Expand Down Expand Up @@ -234,8 +236,9 @@ threshold and 10-minute hold, and cannot divide by zero.
The policy-decision ratio requires 20 aggregate `allow|deny|require-approval|error` decisions and
counts only `error` as failure. It aggregates away the closed verb and every source label.
The refusal-only authentication warning requires at least 20 aggregate refusals, zero accepted
attempts over the same 15-minute window, at least one accepted-outcome sample during the most recent
10 minutes, and a 10-minute hold. It is deliberately not a refusal ratio: without an
attempts over the same 15-minute window, at least one recent scraped sample from the preinitialized
accepted-outcome series during the most recent 10 minutes, and a 10-minute hold. That sample proves
series visibility, not an accepted event. It is deliberately not a refusal ratio: without an
environment-specific baseline, a generic percentage would create an arbitrary security threshold.
Missing or stale accepted-series data cannot satisfy the expression.
The missing-telemetry warning evaluates the existing traffic-independent `sith_build_info` gauge,
Expand Down
12 changes: 7 additions & 5 deletions docs/specs/E2-readfed-brain-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -756,9 +756,10 @@ lenses are covered by an installed connector. Otherwise it **abstains** (§2.6,
| R6 node pressure | K8s (Node) | — | K8s Events + cloud autoscaler | **Prometheus** (quantify) | **Kubernetes** (detect) **+ Prometheus** (quantify) + cloud (autoscaler) |

**Reading the map:** with only the **Wave-1 core (Kubernetes + Argo + GitHub + Prometheus + a log
store)**, all six rules reach at least a *detect* verdict, and R1/R2/R4/R5/R6 reach *confident*. R3's
confidence needs a log connector. This is why W1 is the daily core — it is precisely the coverage the
six rules need.
store)**, all six rules reach at least a *detect* verdict, and R1/R2/R3/R4/R5 reach *confident*.
R6 reaches detection plus Prometheus-backed quantification; it requires cloud-autoscaler facts for
a *confident* verdict. This is why W1 is the daily core — it provides the common coverage while
keeping cloud-specific R6 confidence conditional on the cloud adapter.

### 4.4 Scope-discipline call-outs (anti-drift, from SCOPE §10)

Expand Down Expand Up @@ -832,8 +833,9 @@ the plan-renderer forks.

- [ ] Every connector in §4.2 declares its **kind** (RA/BR/TA), its **verb subset**, and the
**lenses** it feeds; the framework rejects an out-of-taxonomy connector (E12/F12.2).
- [ ] With **only the Wave-1 core** installed, R1/R2/R4/R5/R6 reach a *confident* verdict and R3
reaches at least *detect* — matching the coverage map (§4.3).
- [ ] With **only the Wave-1 core** installed, R1/R2/R3/R4/R5 reach a *confident* verdict and R6
reaches detection plus Prometheus-backed quantification; cloud-autoscaler facts are required
for R6 confidence — matching the coverage map (§4.3).
- [ ] **Scope discipline holds:** Fluentd/FluentBit expose LIVE health only (no log ingestion through
them); Grafana is deep-link only; Helm/Kustomize expose no action verbs in v1.
- [ ] Each connector's **mode** (local / hub / both) is honored — a local-only run uses no
Expand Down
2 changes: 1 addition & 1 deletion internal/observability/alert_rules_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestPortableAlertRulesStayBoundedAndStatic(t *testing.T) {
severity: "warning", hold: "10m",
expr: `sum(increase(sith_auth_attempts_total{outcome="refused"}[15m])) >= 20 and sum(increase(sith_auth_attempts_total{outcome="accepted"}[15m])) == 0 and sum(count_over_time(sith_auth_attempts_total{outcome="accepted"}[10m])) > 0`,
summary: "Sith hub authentication traffic is persistently refusal-only",
description: "At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; accepted-outcome telemetry was present during the last ten minutes.",
description: "At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; a recent scraped sample from the preinitialized accepted-outcome series was present during the last ten minutes.",
},
"SithHubFederationSnapshotFailureRatioHigh": {
severity: "warning", hold: "10m",
Expand Down
2 changes: 1 addition & 1 deletion monitoring/sith-hub.rules.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ tests:
severity: warning
exp_annotations:
summary: Sith hub authentication traffic is persistently refusal-only
description: At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; accepted-outcome telemetry was present during the last ten minutes.
description: At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; a recent scraped sample from the preinitialized accepted-outcome series was present during the last ten minutes.
runbook_url: https://github.com/ArdurAI/sith/blob/dev/docs/runbooks/hub-alerts.md#sithhubauthenticationrefusalonly
- eval_time: 26m
alertname: SithHubAuthenticationRefusalOnly
Expand Down
2 changes: 1 addition & 1 deletion monitoring/sith-hub.rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ groups:
severity: warning
annotations:
summary: Sith hub authentication traffic is persistently refusal-only
description: At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; accepted-outcome telemetry was present during the last ten minutes.
description: At least twenty aggregate authentication attempts were refused and none were accepted over fifteen minutes; a recent scraped sample from the preinitialized accepted-outcome series was present during the last ten minutes.
runbook_url: https://github.com/ArdurAI/sith/blob/dev/docs/runbooks/hub-alerts.md#sithhubauthenticationrefusalonly

- alert: SithHubFederationSnapshotFailureRatioHigh
Expand Down
12 changes: 11 additions & 1 deletion sessions/2026-07-16-argocd-application-facts.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- Effort: standard
- Branch: `gnanirahulnutakki/feat/argocd-application-facts`
- Issue: `#206`
- Status: locally verified; awaiting signed PR and exact post-merge proof
- Status: landed on `dev` through #208; exact post-merge proof recorded below

## Goal

Expand Down Expand Up @@ -70,6 +70,16 @@ rejecting query/fragment credentials, local paths, and unsupported schemes.
- Notion decision: `3a02637e-db07-8194-8160-e78cb189cc86`.
- Notion session: `3a02637e-db07-8143-9bf5-f5629753a902`.

## Landed closure

- Issue #206 closed after PR #208 merged into `dev` on 2026-07-17.
- Exact signed/DCO feature commit: `73ea5cc970f49b2f1a67730e3a5c42489edb594d`.
- Exact merge commit: `311eb1c6c25f0c7dc76487fe0bedfa3a3dde6054`.
- Hosted PR CI, release, CodeQL, and CodeRabbit checks all passed.
- Exact post-merge `dev` CI: <https://github.com/ArdurAI/sith/actions/runs/29551987689>.
- Exact post-merge CodeQL: <https://github.com/ArdurAI/sith/actions/runs/29551987371>.
- Post-merge Dependabot, code-scanning, and secret-scanning queues were `0 / 0 / 0`.

Primary compatibility references:

- <https://argo-cd.readthedocs.io/en/stable/user-guide/application-specification/>
Expand Down
2 changes: 1 addition & 1 deletion sessions/2026-07-16-hub-spoke-worker-pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Bound and parallelize one workspace refresh so unavailable spokes do not delay h

- Focused `go test -race ./internal/hubfleet` passed.
- Synchronization-heavy cancellation and admission tests passed 100 repeated race-detector runs.
- The four-spoke timeout regression completes in one one-second parallel wave. Its one-worker negative control failed as intended at 4.004 seconds.
- The four-spoke timeout regression completes in a single one-second parallel wave. Its one-worker negative control failed as intended at 4.004 seconds.
- Red-team review found and repaired a worker-goroutine panic escape and panic-path worker leak; transport and store panic regressions now prove closed errors, peer cancellation/join, and clean later refreshes.
- Independent CodeRabbit review completed twice; the exact final tree returned zero findings across all six changed files.
- `make ci` passed formatting, vet, lint with zero findings, vulnerability scanning with no findings, the full race suite, safety scripts, and build.
Expand Down
6 changes: 4 additions & 2 deletions sessions/2026-07-16-kubeconfig-directory-race.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ Keep directory import bound to the originally selected directory and prevent val
- Open one descriptor-backed `os.Root` after validating the selected directory identity.
- Traverse and open entries only through that root.
- Verify the opened root and regular files match the identities observed before parsing.
- Reject deferred local credential files and path-based exec commands after the root closes.
- Reject deferred CA, client certificate/key, token-file, and path-based exec reads; embedded data and PATH-based exec commands remain supported.
- Reject deferred local credential files and exec commands that name an absolute or relative
executable path after the root closes.
- Reject deferred CA, client certificate/key, token-file, and executable-path reads; embedded data
and bare exec commands resolved through `PATH` remain supported.
- Preserve entry-count, depth, and byte bounds plus relative, content-free diagnostics.
- Keep generic table pagination, watch bootstrap bounds, and hub concurrency findings out of this slice.

Expand Down
5 changes: 3 additions & 2 deletions sessions/2026-07-18-e10-auth-refusal-only-alert.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ inventing a workload-independent ratio, attributing an actor, or claiming attack
severity labels plus static annotations.
- Stay quiet when the accepted series is missing. Partial telemetry cannot prove refusal-only
traffic; the separate missing-telemetry rule remains the metamonitoring signal.
- Require at least one accepted-outcome sample during the most recent 10 minutes. This prevents old
samples in the 15-minute range from satisfying the denominator after accepted telemetry stops.
- Require at least one recent scraped sample from the preinitialized accepted-outcome series during
the most recent 10 minutes. This proves series visibility, not an accepted event, and prevents old
samples in the 15-minute range from satisfying the freshness guard after accepted telemetry stops.
- Treat any accepted verifier decision as suppression, even if later workspace authorization
denies the request.

Expand Down
Loading