feat(dar): Granted lifecycle, filters, sort, and self-service create policy#28044
Conversation
…ate policy Splits the Data Access Request lifecycle into Approved (awaiting grant) and Granted (active access) so the UI can show an "approved – awaiting grant" banner that clears once an admin marks the request as granted. Adds an indexed approvedBy/approvedById/approvedAt on Task, captured at the approve transition through a new direct-persist helper. Introduces a dedicated /v1/tasks/dataAccessRequests endpoint pre-scoped to category=DataAccess with DAR filters (dataset, service, status, requestedBy, approver, accessType) and an asc/desc sort on createdAt; generic /v1/tasks gains service/approver filters too. DataConsumerPolicy now grants Create on resource=task so authenticated non-admins can file a DAR (fixes "operations [Create] not allowed"). Reworks the workflow handler so transitions whose targetTaskStatus is non-terminal (Approved, Granted) don't close the task, and updates CreateTask.isTerminalTaskStatus to allow advancing between Approved → Granted stages. Adds a new "active" statusGroup that includes the DAR lifecycle states while preserving the existing open/closed semantics that Glossary-style workflows depend on. Includes a Postgres + MySQL migration for the indexed approvedById generated column and integration coverage in DataAccessRequestIT spanning the new lifecycle, filters, sorting, approver capture, and the non-admin policy path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ TypeScript Types Auto-UpdatedThe generated TypeScript types have been automatically updated based on JSON schema changes in this PR. |
There was a problem hiding this comment.
Pull request overview
This PR extends the Data Access Request (DAR) task workflow to support a non-terminal Approved → Granted lifecycle, adds a dedicated DAR listing endpoint with richer filtering/sorting, and updates policy + schema/migrations to persist and query approver metadata efficiently.
Changes:
- Added
Grantedtask status plusapprovedBy/approvedById/approvedAtfields, with workflow updates to supportmarkAsGrantedand revoke from both Approved/Granted. - Introduced
GET /v1/tasks/dataAccessRequestswith DAR-scoped filters and offset pagination; expanded generic task filters (approver/aboutService/accessType) and addedactivestatusGroup. - Updated DataConsumer policy to allow authenticated users to create tasks, plus DB migrations to index
approvedByIdfor filtering performance.
Reviewed changes
Copilot reviewed 37 out of 42 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| openmetadata-ui/src/main/resources/ui/src/rest/tasksAPI.ts | Adds Granted, DataAccessType, active statusGroup, and DAR list API typings. |
| openmetadata-ui/src/main/resources/ui/src/hooks/useDataAccessRequest.ts | Switches hook to DAR-specific endpoint and adds “awaiting grant” state for banner/disable logic. |
| openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx | Renders info banner when the current user’s DAR is Approved (awaiting grant). |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json | Adds label/message keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json | Adds corresponding i18n keys for DAR lifecycle, filters, and banner text. |
| openmetadata-spec/src/main/resources/json/schema/entity/tasks/task.json | Adds Granted enum + approver capture fields to Task schema. |
| openmetadata-spec/src/main/resources/json/schema/api/tasks/taskCount.json | Adds approved and granted counters to task count schema. |
| openmetadata-service/src/main/resources/json/data/policy/DataConsumerPolicy.json | Grants authenticated users Create permission on task. |
| openmetadata-service/src/main/resources/json/data/governance/workflows/DataAccessRequestTaskWorkflow.json | Updates DAR workflow stages/transitions for Approved→Granted lifecycle. |
| openmetadata-service/src/main/java/org/openmetadata/service/tasks/TaskWorkflowHandler.java | Captures approver for non-terminal approve transitions; treats Approved/Granted as non-terminal in resolution fallback. |
| openmetadata-service/src/main/java/org/openmetadata/service/resources/tasks/TaskResource.java | Adds new /dataAccessRequests endpoint; expands /tasks filters; extends resolvable statuses. |
| openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TaskRepository.java | Adds DAR list method with offset pagination + createdAt sorting; adds approver persistence helper. |
| openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ListFilter.java | Adds active statusGroup and new filter conditions (approver/aboutService/accessType). |
| openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java | Extends task count summary and adds DAO queries for createdAt-sorted offset pagination. |
| openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/elements/nodes/userTask/CreateTask.java | Treats Approved/Granted as non-terminal statuses. |
| openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/tasks/TaskService.java | Adds SDK helper for /dataAccessRequests endpoint. |
| openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DataAccessRequestIT.java | Adds/updates IT coverage for Approved→Granted lifecycle, policy, and DAR list filters. |
| openmetadata-integration-tests/pom.xml | Adds test dependencies for PDF/XLSX fixture generation. |
| bootstrap/sql/migrations/native/2.0.1/postgres/schemaChanges.sql | Adds generated approvedbyid column + index for approver filtering (Postgres). |
| bootstrap/sql/migrations/native/2.0.1/mysql/schemaChanges.sql | Adds generated approvedById column + index for approver filtering (MySQL). |
Comments suppressed due to low confidence (1)
openmetadata-ui/src/main/resources/ui/src/hooks/useDataAccessRequest.ts:114
- Same timestamp issue in the stage-based fallback:
isDarApprovalActiveis called withtask.updatedAt ?? task.createdAteven when the task is in the approved/granted stage. This should use the persisted approval timestamp (task.approvedAt) to avoid duration calculations being affected by later transitions.
const stage = (
task.workflowStageDisplayName ??
task.workflowStageId ??
''
).toLowerCase();
if (stage === 'approved' || stage === 'granted') {
const payload = task.payload as
| { duration?: string; expirationDate?: number }
| undefined;
return isDarApprovalActive(
task.updatedAt ?? task.createdAt,
payload?.duration,
payload?.expirationDate
);
…tTaskStatus, document status-group semantics - Replace hardcoded `"approve".equals(transitionId)` checks in TaskWorkflowHandler with a `targetTaskStatus == Approved` helper so the approver-capture path isn't coupled to the workflow JSON's literal transition id. - Document the intentional dual membership of `Approved` in the `active` and `closed` status groups (and in `completedCount` / `approvedCount`): the same status has different lifecycle meanings for Glossary-style workflows (terminal) vs Data Access Requests (awaiting grant), and removing it from `closed` would regress the existing Closed tab for legacy workflows. - Use the persisted `task.approvedAt` (with fallback to updatedAt/createdAt) for `isDarApprovalActive` duration calculations in the DAR hook so later workflow transitions don't shift the apparent approval timestamp. - Add trailing newline to DataConsumerPolicy.json. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…migration, fix CreateTaskTest - /v1/tasks/dataAccessRequests now runs the same `authorizer.authorize(...)` + `EntityUtil.addDomainQueryParam(...)` calls that `listInternal` applies on the generic /v1/tasks endpoint, so the DAR endpoint enforces permissions and domain scoping equivalently. The endpoint still uses offset-based pagination + createdAt sort (so we can't reuse listInternal directly). - Update the statusGroup OpenAPI description and allowableValues to reflect the actual server semantics: 'open' = Open/InProgress/Pending, 'active' = Open/InProgress/Pending/Approved/Granted (DAR-friendly), 'closed' = Approved/Rejected/Completed/Cancelled/Failed/Revoked (keeps Approved for backward compat with non-DAR workflows where Approved is terminal). - Replace the unsupported `ADD COLUMN IF NOT EXISTS` / `ADD KEY IF NOT EXISTS` in the MySQL 2.0.1 migration with information_schema-guarded prepared statements, mirroring the idempotent ALTER pattern used elsewhere in the repo. `ADD KEY IF NOT EXISTS` is not valid MySQL syntax and `ADD COLUMN IF NOT EXISTS` only works on 8.0.29+. - Update CreateTaskTest so the assertions match the new `isTerminalTaskStatus` semantics: Approved and Granted are non-terminal (so the next-stage CreateTask listener can advance the DAR through ApprovedAccess → GrantedAccess); Revoked is terminal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…wable race CI flaked once on createApproveGrantRevokeLifecycle:213 with `Workflow resolution failed for task ... on transition 'revoke'`. The Task entity is correctly updated for the new GrantedAccess stage (the preceding assertions on status=Granted, stageId=granted, and availableTransitions=[revoke] all pass), but Flowable's runtime-task wait state occasionally hasn't settled the instant `markAsGranted` returns. The next `resolveTask` call then sees an active task with no matching pending transition and bubbles up the error. Wrap the revoke `.resolve(...)` in `await().atMost(5s).pollInterval(250ms)` that ignores `ApiException`. Locally the suite still completes in ~5–7s with zero retries, matching the previous fast-path, so this is purely defensive in CI. DataAccessRequestIT 15/15 still passing after a full clean rebuild of spec+service+sdk. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The Java checkstyle failed. Please run You can install the pre-commit hooks with |
…xOrCondition column scope Two Copilot review-comment doc fixes (no behavior change): - TaskWorkflowHandler.resolveResolutionType: expand the docstring to make the cascade explicit and call out the convention for custom workflows. Approved/Granted intentionally fall through to null in the targetTaskStatus fallback so DAR (and any future workflow that uses Approved/Granted as a non-terminal "awaiting next step" state) keeps the task alive on the next user-task node. Custom workflows that intend an Approved transition to be terminal MUST declare an explicit `resolutionType` in their workflow JSON, matching the seeded GlossaryApproval / DescriptionUpdate / etc. definitions. - ListFilter.buildFqnPrefixOrCondition: rewrite the docstring to make it explicit that the helper is purpose-built for `task_entity.aboutFqnHash`. Both callers (aboutEntity and aboutService) operate on that single column — the `prefix` arg only namespaces bound parameter keys. Warn against reuse with other columns so future callers don't accidentally inherit the wrong column choice. DataAccessRequestIT 15/15 still passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rAwaitingGrant on approval-active Three open Copilot/gitar-bot review fixes: - DataAssetsHeader.test.tsx: drop the unused `listTasks: jest.fn()` mock. The component now calls `listDataAccessRequests` exclusively (the per-asset DAR hook was switched to it earlier in this PR). The dangling mock kept the test surface out of sync with what the code actually calls. - DataAccessRequestIT.java: replace the inlined `org.openmetadata.sdk.exceptions.ApiException.class` in the awaitility retry with a proper top-level import, matching the project's no-FQN convention (and the existing InvalidRequestException import sitting one line above). - useDataAccessRequest.isDarAwaitingGrant: short-circuit to false when an approved DAR's duration / expirationDate window has elapsed. Previously the banner could surface for an expired approval while the "Request Data Access" button was simultaneously enabled (because isDarDisabled already runs the same isDarApprovalActive gate). Reuse approvedAt-based start time + payload duration/expirationDate so both memos agree on whether the approval is still active. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Conflicts: 10 locale files (ar-sa, gl-es, ko-kr, mr-in, nl-nl, pr-pr, pt-pt, th-th, tr-tr, zh-tw). main rev e5accb3 shipped a translation update via PR #28119 that overlapped the DAR keys this branch added in en-us. Took main's per-locale versions verbatim, then re-ran `yarn i18n` to repropagate the 14 DAR keys (access-type, approver, data-access-request*, grant-access, granted, mark-as-granted, requested-by, sort-{ascending,descending,order}) from en-us across all 17 locales. No code conflicts; the merge is purely an i18n refresh. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| "access-policy-name": "نام سیاست دسترسی", | ||
| "access-request-plural": "درخواستهای دسترسی", | ||
| "access-token": "توکن دسترسی", | ||
| "access-type": "Access Type", |
There was a problem hiding this comment.
💡 Quality: Locale keys reverted from translated to English
Several locale keys that were previously translated are now being reverted to English across multiple locales:
"access-type"changed from localized text to"Access Type"in pr-pr, mr-in, th-th, zh-tw"approver"changed from localized text to"Approver"in pr-pr, mr-in, th-th, zh-tw
This appears to be an unintentional regression from the i18n sync. If these terms are intended to remain as untranslated proper nouns/technical terms, this should be documented. Otherwise, the original translations should be preserved.
Was this helpful? React with 👍 / 👎
Code Review 👍 Approved with suggestions 10 resolved / 11 findingsImplements a 'Granted' state for Data Access Requests with updated lifecycle management, granular filtering, and policy-based access. Please address the regression where several locale keys were reverted from translated values to English. 💡 Quality: Locale keys reverted from translated to English📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json:19 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json:158 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json:19 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json:158 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json:19 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json:158 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json:19 📄 openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json:158 Several locale keys that were previously translated are now being reverted to English across multiple locales:
This appears to be an unintentional regression from the i18n sync. If these terms are intended to remain as untranslated proper nouns/technical terms, this should be documented. Otherwise, the original translations should be preserved. ✅ 10 resolved✅ Bug: 'Approved' status present in both 'active' and 'closed' groups
✅ Quality: Hardcoded 'approve' transition ID couples handler to workflow JSON
✅ Quality: Missing newline at end of DataConsumerPolicy.json
✅ Bug: isDarDisabled missing 'granted' stage — allows duplicate DARs
✅ Quality: Unused TaskEntityStatus import in isDarDisabled after refactor
...and 5 more resolved from earlier reviews 🤖 Prompt for agentsOptionsDisplay: compact → Showing less information. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
|
|



Describe your changes:
I added a
Grantedstate and filterable list to the Data Access Request workflow, gave authenticated users permission to file a DAR, and fixed the related workflow-handler bugs that surfaced onceApprovedbecame a non-terminal state.Type of change:
High-level design:
Lifecycle. The DAR workflow now goes
Open → Approved (awaiting grant) → Granted (active access) → Revoked, withApprovedandGrantedadded toTaskEntityStatus. The UI hook (useDataAccessRequest) andDataAssetsHeaderrender an info banner while a DAR for the current user is inApproved, and clear it once it transitions toGranted. Approver capture is wired through a newTaskRepository.persistApprover()helper that goes throughstoreEntity+postUpdateso the newapprovedBy/approvedById/approvedAtfields are persisted reliably on both terminal and non-terminal approve transitions.Filters. Added a dedicated
/v1/tasks/dataAccessRequestssub-endpoint that pre-scopes tocategory=DataAccess,type=DataAccessRequestand exposesdataset,service,status,requestedBy,approver,accessType,sortOrder(asc/desc oncreatedAt), plus offset-based pagination. Generic/v1/tasksgainsaboutService,approver, andapproverIdfilters so other task types benefit too. NewListFilterconditions cover the approver (indexedapprovedByIdcolumn with FQN fallback), the service via FQN-hash prefix, andpayload.accessTypevia the existing@ConnectionAwareSqlQueryJSON-extract pattern.Policy. Adds a
DataConsumerPolicy-CreateTask-RulegrantingCreateon resourcetaskto authenticated users, fixing theoperations [Create] not allowederror a non-admin saw when trying to request access.Workflow-handler fixes discovered while writing integration tests:
resolveResolutionTypeno longer mapsApproved/Grantedto a terminalTaskResolutionTypein the fallback switch — the workflow stays alive so the request can later be granted or revoked.CreateTask.isTerminalTaskStatusnow treatsApprovedandGrantedas non-terminal, allowing the next-stage CreateTask to actually update the existing task'sstatus/workflowStageId/availableTransitionsinstead of preserving stale state during themarkAsGrantedtransition.activevalue forstatusGroup(Open + InProgress + Pending + Approved + Granted) so the DAR hook can find "still in progress" requests without altering the existingopen/closedsemantics that Glossary-style workflows depend on.Migration. In
bootstrap/sql/migrations/native/2.0.0/{mysql,postgres}/schemaChanges.sqlthe newapprovedByIdgenerated column +idx_approved_by_idindex are declared inline on thetask_entityCREATE TABLE for fresh installs, and an idempotent guarded ALTER block in the same file attaches the column + index for existing 2.0.0 deployments where the CREATE TABLE IF NOT EXISTS is a no-op (information_schema-guarded prepared statements on MySQL, nativeADD COLUMN IF NOT EXISTSon Postgres). 2.0.0 has not been released yet, so no data backfill is needed.Tests:
Use cases covered
POST /v1/tasks(was previously denied by policy).ApprovedwithapprovedBy/At/ByIdpopulated and bothmarkAsGrantedandrevoketransitions surfaced.GrantedwithapprovedBypreserved.Approved(back out before granting) orGranted(revoke active access) → task ends inRevokedwith aRevokedresolution./v1/tasks/dataAccessRequestshonorsdataset,accessType,status,approverId, andsortOrder=asc|desc, and never leaks non-DAR task types into the list.closedinTaskCount.openCount/completedCount(no regression).Backend integration tests
openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DataAccessRequestIT.java(8 new + 3 updated test cases). Verified by runningmvn test -pl openmetadata-integration-tests -Dtest='DataAccessRequestIT,TaskResourceIT,IncidentTaskIntegrationIT'— 257 tests pass, 0 failures.Playwright (UI) tests
Manual testing performed
make generateregenerates Pydantic + Java POJOs cleanly after thetask.jsonandtaskCount.jsonschema edits and that the newGrantedenum +approvedBy*fields appear intarget/generated-sources.mvn spotless:applyandyarn ui-checkstyle:changedon the touched files;yarn i18nsynced the 13 new locale keys across all 17 locale files.UI screen recording / screenshots:
Not applicable. The only UI change is an Ant Design
Alertbanner shown when a request is in theApproved(awaiting-grant) state; the dedicated DAR list page is a follow-up.Checklist:
bootstrap/sql/migrations/native/2.0.0/{mysql,postgres}/schemaChanges.sqlfor the indexedapprovedByIdcolumn (inline in the CREATE TABLE for fresh installs, idempotent guarded ALTER for existing 2.0.0 deployments).DataAccessRequestIT) and listed them above.🤖 Generated with Claude Code