Skip to content

feat(data-quality): activate W65 lifecycle API - #261

Merged
akhiabanchian merged 16 commits into
mainfrom
w65-data-quality-api-ui-closeout
Oct 7, 2026
Merged

akhiabanchian merged 16 commits into
mainfrom
w65-data-quality-api-ui-closeout

Conversation

@ammarheidari

Copy link
Copy Markdown
Contributor

Authority

W65 / #214 Slices 1–4C are protected-main admitted through PR #254. The remaining scope is API/UI closeout.

API activation slice

  • optional Kafdeck:DataQuality runtime configuration, disabled by default;
  • explicit SQLite/PostgreSQL durable lifecycle-store activation;
  • fail-closed provider/execution-mode/path/secret validation;
  • read-only API activation independent of lifecycle management;
  • lifecycle management requires explicit ManagementEnabled=true and OIDC;
  • explicit DataQualityRead / DataQualityManage authorization actions;
  • bounded policy list/detail/evidence endpoints;
  • revision-guarded create/replace/state lifecycle operations;
  • route-owned cluster/policy identity prevents cross-cluster policy takeover;
  • aggregate/progress-only evidence projection — no raw key/value/header/payload surface;
  • real PostgreSQL persistence coverage in the v05 gate;
  • seekable provider-neutral policy listing without nullable PostgreSQL cursor parameters.

Safety

  • no arbitrary-code predicates;
  • no raw payload durability or API exposure;
  • no hidden Kafka consumer ownership or offset commits;
  • no background monitoring-principal bypass;
  • management mutations remain antiforgery-protected and OIDC-gated;
  • UI parity remains a following slice after backend admission.

Refs #214 #209.

Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-07T18:49:48.228404Z 2e4f304 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copy link
Copy Markdown
Contributor Author

@codex review

Please review exact head e840c2f835e4cafa2244059e96e551b3775dcf2d only. Focus on W65 API activation boundaries: disabled-by-default/fail-closed configuration, SQLite/PostgreSQL parity, nullable-list query portability and index-seek behavior, route-owned cluster/policy identity, optimistic revision/CAS semantics, explicit DataQualityRead/DataQualityManage authorization, OIDC + antiforgery management gating, aggregate-only evidence projection, and ensuring no raw payload or hidden monitoring-principal bypass is introduced.

akhiabanchian
akhiabanchian previously approved these changes Oct 7, 2026
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>

Copy link
Copy Markdown
Contributor Author

@codex review

Please review corrective exact head 9637915bd05528da171ef92ffb78da0676fc0cfd only. The change makes IDataQualityLifecycleStore binding explicit with [FromServices] so GET route mapping cannot infer a request body. Re-verify the full W65 API activation boundaries, PostgreSQL/list portability, CAS/lifecycle semantics, explicit authorization, OIDC/antiforgery management gating and aggregate-only evidence surface.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 9637915bd0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Signed-off-by: Ammar Heidari <ammar@arad-itc.org>

Copy link
Copy Markdown
Contributor Author

@codex review

Please review corrective exact head 1e5354ef353fdfc37496f86019c1f577872b2812 only. The PostgreSQL integration gate exposed an actual stale-CAS rollback bug: the RETURNING reader remained active when RollbackAsync was attempted. The reader is now explicitly disposed before rollback. Re-verify provider parity, lifecycle CAS semantics, API/security boundaries, and that no new raw-data or authorization surface was introduced.

Signed-off-by: Ammar Heidari <ammar@arad-itc.org>

Copy link
Copy Markdown
Contributor Author

@codex review

Please review final security-corrective exact head 408caaf3ac3a327db884c8cad7c65918afbc6210 only. In addition to the PostgreSQL stale-CAS reader/rollback fix, policy-specific detail/evidence/manage routes now bind DataQualityRead/DataQualityManage authorization to both clusterId and policyId, while list remains cluster-scoped. Re-verify cross-cluster/resource isolation, provider parity, CAS semantics, OIDC/antiforgery gating and aggregate-only evidence exposure.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 1e5354ef35

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

akhiabanchian
akhiabanchian previously approved these changes Oct 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 408caaf3ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/backend/Kafdeck.Api/KafdeckDataQualityEndpoints.cs Outdated
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>
Signed-off-by: Ammar Heidari <ammar@arad-itc.org>

Copy link
Copy Markdown
Contributor Author

@codex review

Please review final P1-corrective exact head 2e4f30496ba77b65376cc7a429b39317af6ce321 only. Underlying topic visibility is now enforced independently of DataQuality permission: list uses collection preflight plus per-item conjunction of DataQualityRead(policyId) and TopicRead(topicName); detail/evidence/manage re-authorize the resolved/proposed topic and audit denials. The response marks authorization-filtered collections without exposing raw record material. Also re-verify PostgreSQL CAS parity, OIDC/antiforgery management gating, cross-cluster protection and bounded pagination.

@akhiabanchian
akhiabanchian merged commit 76f6346 into main Oct 7, 2026
9 checks passed
@akhiabanchian
akhiabanchian deleted the w65-data-quality-api-ui-closeout branch October 7, 2026 18:49

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e4f30496b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +80 to +81
page.Truncated,
page.NextPolicyId,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Hide unauthorized policy IDs in pagination cursors

When a truncated raw page ends with an unauthorized policy, page.NextPolicyId still contains that hidden policy's ID even though the policy was removed from visible. For example, with maxResults=1 and a hidden first policy followed by another record, the response has no items but exposes the hidden ID as its continuation cursor, contradicting the intended authorization-filtered response boundary. Use an opaque server-owned cursor or otherwise avoid serializing an unauthorized policy identifier.

Useful? React with 👍 / 👎.

Comment on lines +256 to +259
page.Points
.Select(
DataQualityEvidenceData.From)
.ToArray(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Authorize every returned evidence topic

When a policy is moved from topic A to topic B, QueryEvidenceAsync still returns historical points for all policy versions, and each point preserves its own topic name. Fresh evidence in this head is that the new check authorizes only the current policy snapshot's topic B, while this mapping serializes old topic-A points without a per-point TopicRead check; a reader allowed for B but denied A can therefore retrieve A's name and aggregate evidence. Filter or reject points by their actual topic and audit any resulting denial.

Useful? React with 👍 / 👎.

Comment on lines +460 to +464
var updated =
await store.SetPolicyStateAsync(
policyId,
request.State,
request.ExpectedRevision,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bind topic authorization to the CAS revision

If request.ExpectedRevision is greater than the fetched snapshot's revision, a concurrent replacement can move the policy to an unauthorized topic and reach that expected revision between the topic check and this CAS. The state update then succeeds and returns the concurrent revision's complete definition, leaking the unauthorized topic and mutating it without authorization; the replacement route has the same future-revision race. Require the supplied revision to equal the snapshot that was authorized, or perform authorization against the definition atomically selected by the CAS.

Useful? React with 👍 / 👎.

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.

2 participants