Skip to content

feat(asana): expand provider to 101 core REST actions - #215

Merged
BlackHole1 merged 12 commits into
oomol-lab:mainfrom
cctv1005s:feat/asana-core-actions
Jul 27, 2026
Merged

feat(asana): expand provider to 101 core REST actions#215
BlackHole1 merged 12 commits into
oomol-lab:mainfrom
cctv1005s:feat/asana-core-actions

Conversation

@cctv1005s

Copy link
Copy Markdown
Contributor

Summary

  • expand the Asana provider from its original small action set to 101 core collaboration REST actions across workspaces, users, teams, projects, sections, tasks, stories/comments, tags, custom fields/settings, and attachments
  • add a shared typed Asana runtime with consistent pagination, error mapping, request validation, and injected SSRF-guarded egress
  • complete advanced project/task search filters, asynchronous duplicate job responses, date and placement constraints, and official provider scopes
  • support safe external and transit-file attachments with public URL validation, multipart uploads, encoded filenames, and the 100 MiB limit
  • keep provider loading lazy and split definitions/runtime by resource responsibility

Reference: https://developers.asana.com/reference/rest-api-reference

Verification

  • npm run fix-check
  • npx vitest run src/providers/asana/runtime.test.ts — 259 passed
  • npm test — 59 files, 825 tests passed
  • npm run build
  • catalog generation — 1129 providers, 12254 actions
  • verified 101 unique Asana definitions match 101 executors
  • built and smoke-tested the Docker image locally; health passed and the live catalog exposed all 101 Asana actions

Notes

  • specialized and enterprise-oriented Asana resource families remain out of scope
  • the provider continues to use Personal Access Token authentication; OAuth-only attachment app linking is intentionally not exposed

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d10cfa74-9c78-4870-a078-825ee6438dff

📥 Commits

Reviewing files that changed from the base of the PR and between 8250d62 and 3683051.

📒 Files selected for processing (8)
  • src/providers/asana/actions-custom-fields.ts
  • src/providers/asana/actions-projects.ts
  • src/providers/asana/runtime-attachments.ts
  • src/providers/asana/runtime-custom-fields.ts
  • src/providers/asana/runtime-projects-sections.ts
  • src/providers/asana/runtime-tasks.ts
  • src/providers/asana/runtime.test.ts
  • src/providers/asana/runtime.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/providers/asana/runtime.ts
  • src/providers/asana/actions-projects.ts
  • src/providers/asana/actions-custom-fields.ts
  • src/providers/asana/runtime-custom-fields.ts
  • src/providers/asana/runtime-projects-sections.ts
  • src/providers/asana/runtime-attachments.ts
  • src/providers/asana/runtime-tasks.ts
  • src/providers/asana/runtime.test.ts

Summary by CodeRabbit

  • New Features
    • Expanded Asana support from 10 actions to 100+ across workspaces, users, teams, projects, sections, tasks, comments, tags, custom fields, and attachments.
    • Added project/task search, duplication, memberships/followers, dependencies, section/task insertion ordering, cursor pagination, and workspace event sync.
    • Added attachment creation with local file uploads or validated public URLs (with size and security checks).
  • Bug Fixes
    • Improved request/response validation, error mapping, and pagination/offset cursor handling; normalized mutation responses consistently.
  • Documentation
    • Published an end-to-end implementation plan and design specification for the expanded Asana core actions.

Walkthrough

The Asana provider is reorganized into resource-specific action definitions and runtime handlers. Shared schemas, pagination, request envelopes, error mapping, and response normalization are centralized. New handlers cover workspaces, users, teams, projects, sections, tasks, stories, tags, custom fields, settings, and attachments. Attachment creation supports either public external URLs or transit-file multipart uploads. Runtime tests cover catalog parity, request construction, validation, pagination, errors, and upload behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AsanaActionHandler
  participant AsanaRuntime
  participant AsanaAPI
  Client->>AsanaActionHandler: invoke provider action
  AsanaActionHandler->>AsanaRuntime: validate and construct request
  AsanaRuntime->>AsanaAPI: send authenticated request
  AsanaAPI-->>AsanaRuntime: return data envelope or error
  AsanaRuntime-->>AsanaActionHandler: normalize response
  AsanaActionHandler-->>Client: return action result
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required type(scope): subject format and accurately summarizes the Asana expansion.
Description check ✅ Passed The description is directly aligned with the Asana provider expansion and runtime changes in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (14)
src/providers/asana/runtime-stories-tags.ts (1)

109-119: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider compactAsanaQuery here for consistency.

Every other list handler in this cohort routes optional query values through compactAsanaQuery; this one relies on listAsanaResources dropping the undefined workspace. Using the shared helper keeps the query-building contract uniform.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime-stories-tags.ts` around lines 109 - 119, Update
the list_tags handler to pass its query object through compactAsanaQuery,
including the optional workspace value and buildAsanaPaginationQuery(input,
defaultTagFields), before calling listAsanaResources. Preserve the existing tags
resource and context arguments.
src/providers/asana/runtime-projects-sections.ts (2)

136-157: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Placement check on include is string-based; prefer comparing the parsed array.

optionalDelimitedStringArray already joins the validated array, then Line 139 re-splits it. Keeping the array and joining only at the request boundary avoids the round trip and mis-parse risk if a value ever contains a comma.

♻️ Suggested change
-    const include = optionalDelimitedStringArray(input.include, "include");
+    const includeValues = input.include === undefined ? undefined : requiredNonEmptyStringArray(input.include, "include");
     const scheduleDates = buildScheduleDates(input.scheduleDates);
-    if (scheduleDates && !include?.split(",").includes("task_dates")) {
+    if (scheduleDates && !includeValues?.includes("task_dates")) {
       throw asanaInvalidInputError("scheduleDates requires include to contain task_dates.");
     }
@@
-        include,
+        include: includeValues?.join(","),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime-projects-sections.ts` around lines 136 - 157, The
duplicate_project method should retain the parsed include array from
optionalDelimitedStringArray and use it to check whether "task_dates" is
present, instead of splitting the serialized value again. Join or serialize the
array only when constructing the Asana request body, preserving the existing
validation and payload behavior.

506-580: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated search/filter helper block across two Asana runtime modules. Both modules define their own copies of requiredNonEmptyStringArray, optionalDelimitedStringArray, booleanString, nullableSearchDate, searchFilterScalar, searchFilterNumber, and a custom_fields.* search-query builder, so filter semantics can drift independently.

  • src/providers/asana/runtime-projects-sections.ts#L506-L580: move these helpers into a shared provider-local module (e.g. runtime-search.ts) and import them here.
  • src/providers/asana/runtime-tasks.ts#L515-L580: import the shared helpers instead, passing the extra before/after conditions through a parameter to the shared custom-field query builder.

As per coding guidelines: "Split modules by responsibility or abstraction boundary rather than loose categories."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime-projects-sections.ts` around lines 506 - 580, The
search/filter helpers are duplicated across both runtime modules and must be
centralized. For src/providers/asana/runtime-projects-sections.ts lines 506-580,
move the shared helpers and custom-field query builder into a provider-local
runtime-search module, then import and use them here. For
src/providers/asana/runtime-tasks.ts lines 515-580, remove the duplicate
implementations and import the shared helpers, passing its additional
before/after conditions into the shared custom-field query builder parameter so
existing filter behavior is preserved.

Source: Coding guidelines

src/providers/asana/runtime.test.ts (1)

2884-2907: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Optional expectedOutput lets several workspace/user/team cases skip result assertions.

Cases like add_workspace_user, list_users, create_team, and remove_team_user omit expectedOutput, so their response normalization is never checked. Making expectedOutput required in HandlerCase (or filling it in for those cases) closes the gap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime.test.ts` around lines 2884 - 2907, Require every
workspaceUserTeamHandlerCases entry to define expectedOutput, including
add_workspace_user, list_users, create_team, and remove_team_user, and remove
the conditional guard so each test always asserts the handler result. Update the
HandlerCase type and case fixtures with the correct normalized outputs.
src/providers/asana/runtime-tasks.ts (1)

486-506: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Deriving opt_fields from a body key name is fragile.

Object.keys(body).includes("followers") couples query construction to a payload field name; renaming or adding a followers key elsewhere silently changes request shape. An explicit parameter makes intent local to each call site.

♻️ Suggested change
 async function writeTaskAssociation(
   path: string,
   body: Record<string, unknown>,
   input: Record<string, unknown>,
   context: AsanaContext,
+  includeTaskFields = false,
 ): Promise<Record<string, unknown>> {
   const payload = await requestAsana({
     path,
     context,
     method: "POST",
-    query: Object.keys(body).includes("followers") ? buildAsanaFieldsQuery(input, defaultTaskFields) : undefined,
+    query: includeTaskFields ? buildAsanaFieldsQuery(input, defaultTaskFields) : undefined,
     body,
     notFoundAsInvalidInput: true,
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime-tasks.ts` around lines 486 - 506, Update
writeTaskAssociation to accept an explicit parameter controlling whether
buildAsanaFieldsQuery is used, instead of deriving that choice from the body’s
"followers" key. Pass the appropriate value at each call site so follower
associations retain the opt_fields query while other task associations do not.
src/providers/asana/actions-attachments.ts (1)

25-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate resourceInput helper.

This helper is duplicated verbatim in actions-custom-fields.ts and actions-stories-tags.ts. See consolidated comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-attachments.ts` around lines 25 - 34, Remove the
local resourceInput helper from actions-attachments.ts and reuse the shared
implementation used by actions-custom-fields.ts and actions-stories-tags.ts,
updating imports as needed while preserving its current schema behavior.
src/providers/asana/actions-stories-tags.ts (1)

57-82: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate resourceInput/resourceIdInput/paginatedResourceInput helpers.

Same bodies as the helpers in actions-attachments.ts and actions-custom-fields.ts. See consolidated comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-stories-tags.ts` around lines 57 - 82, Remove the
duplicate resourceInput, resourceIdInput, and paginatedResourceInput helpers
from actions-stories-tags.ts, and reuse the shared implementations from the
existing Asana helper module used by actions-attachments.ts and
actions-custom-fields.ts. Update imports and references as needed while
preserving each helper’s current schema behavior.
src/providers/asana/actions-custom-fields.ts (1)

272-293: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate resourceInput/paginatedResourceInput helpers.

Identical to helpers defined in actions-attachments.ts and actions-stories-tags.ts. See consolidated comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-custom-fields.ts` around lines 272 - 293, Remove
the duplicate resourceInput and paginatedResourceInput helpers from this module
and reuse the shared implementations already defined for Asana actions, updating
imports or references as needed while preserving their existing schemas and
required fields.
src/providers/asana/schemas.ts (1)

146-176: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

compactCustomFieldSettingSchema mistypes team-scoped settings as project-shaped.

compactCustomFieldSettingSchema hardcodes project/parent as projectCompactSchema, but it's reused in teamSchema.custom_field_settings (line 175) where the owning resource is a team. This misdescribes the output shape for list_team_custom_field_settings consumers relying on the schema for discovery.

🛠️ Suggested fix
 const compactCustomFieldSettingSchema = s.looseObject("An Asana custom field setting.", {
   gid: s.string("The custom field setting gid."),
   resource_type: s.string("The resource type."),
-  project: projectCompactSchema,
   is_important: s.boolean("Whether the custom field is marked important."),
-  parent: projectCompactSchema,
+  parent: resourceRefSchema,
   custom_field: compactCustomFieldSchema,
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/schemas.ts` around lines 146 - 176, Update
compactCustomFieldSettingSchema and its use in teamSchema.custom_field_settings
so team-scoped custom field settings describe their team owner rather than
project-shaped project and parent fields. Preserve the existing project-scoped
schema behavior by introducing or reusing a team-specific compact setting schema
for the teamSchema path.
src/providers/asana/actions-tasks.ts (2)

193-193: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

nullableSearchDate duplicates nullableDateSchema.

Same implementation as Line 28; drop it and reuse nullableDateSchema.

♻️ Proposed cleanup
-const nullableSearchDate = (description: string): JsonSchema => s.nullable(s.date(description));
 const searchCustomFieldFilterSchema = s.object(

Then replace nullableSearchDate( usages with nullableDateSchema(.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-tasks.ts` at line 193, Remove the duplicate
nullableSearchDate helper and reuse the existing nullableDateSchema definition
instead. Update every nullableSearchDate usage in the surrounding schema
definitions to call nullableDateSchema, preserving the existing descriptions and
behavior.

484-499: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Non-null assertions on an index-signature record.

taskCreateOnlyFields.followerIds! / .tagIds! rely on Record<string, JsonSchema> indexing. Extracting the two shared field schemas into named consts (or typing taskCreateOnlyFields as an explicit interface) removes the assertions and keeps the contract checked.

As per coding guidelines: "Do not add provider-local tuple builders, as const, satisfies, or as Record<...> casts solely to derive action-name unions or handler maps; prefer simple annotations, explicit records".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-tasks.ts` around lines 484 - 499, Replace the
non-null assertions on taskCreateOnlyFields.followerIds and
taskCreateOnlyFields.tagIds in the add-task input schema with named shared
schema constants, and reuse those constants both in taskCreateOnlyFields and
this schema so their presence is checked without index-signature assertions.
Keep the existing field definitions and validation contract unchanged.

Source: Coding guidelines

src/providers/asana/executors.ts (1)

19-27: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Handler-map merge silently shadows duplicate action names.

With six modules covering ~101 actions, an accidentally repeated action name (e.g. a task-scoped list also defined in the projects module) is silently overwritten by the later map, and catalog-parity tests still pass. A merge that asserts key uniqueness — or a shared provider-runtime helper that does — makes the collision fail loudly at load time. Object spread would also read more idiomatically than Object.assign.

As per coding guidelines: "Avoid repeated action-name wiring; define handlers once and derive executor maps through shared provider runtime helpers when suitable."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/executors.ts` around lines 19 - 27, Update the handlers
map assembly in the provider executor to use the shared provider-runtime helper
or another uniqueness-validating merge instead of Object.assign, so duplicate
action names fail loudly during initialization rather than being overwritten.
Preserve all six handler modules and their existing action mappings, and prefer
the established shared helper when available.

Source: Coding guidelines

src/providers/asana/actions-teams.ts (1)

103-115: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the "at least one mutable field" anyOf pattern into a shared helper.

The same schema.anyOf = Object.keys(fields).map((field) => ({ required: [field] })) construction appears in src/providers/asana/actions-tasks.ts (Line 115) and src/providers/asana/actions-users.ts (Line 28). A single helper in ./schemas.ts would remove the inline IIFE here and keep the semantics consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/actions-teams.ts` around lines 103 - 115, Extract the
repeated “at least one mutable field” anyOf construction into a shared helper in
schemas.ts, then reuse it from the inputSchema definitions in actions-teams.ts,
actions-tasks.ts, and actions-users.ts. Preserve each schema’s existing fields,
required team/user/task identifiers, and helper-generated anyOf semantics while
removing the inline IIFE and duplicated Object.keys mapping.
src/providers/asana/runtime.ts (1)

269-271: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Propagate Asana’s Retry-After on 429 errors.

The 429 branch ignores response.headers.get("Retry-After"); mirror the existing provider pattern and include the retry hint in the ProviderRequestError message/details so clients can back off instead of retrying immediately.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/asana/runtime.ts` around lines 269 - 271, Update the 429
handling branch in the Asana response-error flow to read
response.headers.get("Retry-After") and propagate that retry hint through the
ProviderRequestError message or details, following the existing provider pattern
while preserving the current status and payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-07-27-asana-core-actions.md`:
- Around line 654-655: Replace the hardcoded personal machine paths in the
affected plan steps with a repository-neutral placeholder such as
<OPEN_CONNECTOR_DIR> or an environment-variable-based path, including the
references to docker-compose.yml and docker-compose.override.yml. Apply the same
normalization to all occurrences in the cited ranges while preserving the
referenced files and commands.

---

Nitpick comments:
In `@src/providers/asana/actions-attachments.ts`:
- Around line 25-34: Remove the local resourceInput helper from
actions-attachments.ts and reuse the shared implementation used by
actions-custom-fields.ts and actions-stories-tags.ts, updating imports as needed
while preserving its current schema behavior.

In `@src/providers/asana/actions-custom-fields.ts`:
- Around line 272-293: Remove the duplicate resourceInput and
paginatedResourceInput helpers from this module and reuse the shared
implementations already defined for Asana actions, updating imports or
references as needed while preserving their existing schemas and required
fields.

In `@src/providers/asana/actions-stories-tags.ts`:
- Around line 57-82: Remove the duplicate resourceInput, resourceIdInput, and
paginatedResourceInput helpers from actions-stories-tags.ts, and reuse the
shared implementations from the existing Asana helper module used by
actions-attachments.ts and actions-custom-fields.ts. Update imports and
references as needed while preserving each helper’s current schema behavior.

In `@src/providers/asana/actions-tasks.ts`:
- Line 193: Remove the duplicate nullableSearchDate helper and reuse the
existing nullableDateSchema definition instead. Update every nullableSearchDate
usage in the surrounding schema definitions to call nullableDateSchema,
preserving the existing descriptions and behavior.
- Around line 484-499: Replace the non-null assertions on
taskCreateOnlyFields.followerIds and taskCreateOnlyFields.tagIds in the add-task
input schema with named shared schema constants, and reuse those constants both
in taskCreateOnlyFields and this schema so their presence is checked without
index-signature assertions. Keep the existing field definitions and validation
contract unchanged.

In `@src/providers/asana/actions-teams.ts`:
- Around line 103-115: Extract the repeated “at least one mutable field” anyOf
construction into a shared helper in schemas.ts, then reuse it from the
inputSchema definitions in actions-teams.ts, actions-tasks.ts, and
actions-users.ts. Preserve each schema’s existing fields, required
team/user/task identifiers, and helper-generated anyOf semantics while removing
the inline IIFE and duplicated Object.keys mapping.

In `@src/providers/asana/executors.ts`:
- Around line 19-27: Update the handlers map assembly in the provider executor
to use the shared provider-runtime helper or another uniqueness-validating merge
instead of Object.assign, so duplicate action names fail loudly during
initialization rather than being overwritten. Preserve all six handler modules
and their existing action mappings, and prefer the established shared helper
when available.

In `@src/providers/asana/runtime-projects-sections.ts`:
- Around line 136-157: The duplicate_project method should retain the parsed
include array from optionalDelimitedStringArray and use it to check whether
"task_dates" is present, instead of splitting the serialized value again. Join
or serialize the array only when constructing the Asana request body, preserving
the existing validation and payload behavior.
- Around line 506-580: The search/filter helpers are duplicated across both
runtime modules and must be centralized. For
src/providers/asana/runtime-projects-sections.ts lines 506-580, move the shared
helpers and custom-field query builder into a provider-local runtime-search
module, then import and use them here. For src/providers/asana/runtime-tasks.ts
lines 515-580, remove the duplicate implementations and import the shared
helpers, passing its additional before/after conditions into the shared
custom-field query builder parameter so existing filter behavior is preserved.

In `@src/providers/asana/runtime-stories-tags.ts`:
- Around line 109-119: Update the list_tags handler to pass its query object
through compactAsanaQuery, including the optional workspace value and
buildAsanaPaginationQuery(input, defaultTagFields), before calling
listAsanaResources. Preserve the existing tags resource and context arguments.

In `@src/providers/asana/runtime-tasks.ts`:
- Around line 486-506: Update writeTaskAssociation to accept an explicit
parameter controlling whether buildAsanaFieldsQuery is used, instead of deriving
that choice from the body’s "followers" key. Pass the appropriate value at each
call site so follower associations retain the opt_fields query while other task
associations do not.

In `@src/providers/asana/runtime.test.ts`:
- Around line 2884-2907: Require every workspaceUserTeamHandlerCases entry to
define expectedOutput, including add_workspace_user, list_users, create_team,
and remove_team_user, and remove the conditional guard so each test always
asserts the handler result. Update the HandlerCase type and case fixtures with
the correct normalized outputs.

In `@src/providers/asana/runtime.ts`:
- Around line 269-271: Update the 429 handling branch in the Asana
response-error flow to read response.headers.get("Retry-After") and propagate
that retry hint through the ProviderRequestError message or details, following
the existing provider pattern while preserving the current status and payload.

In `@src/providers/asana/schemas.ts`:
- Around line 146-176: Update compactCustomFieldSettingSchema and its use in
teamSchema.custom_field_settings so team-scoped custom field settings describe
their team owner rather than project-shaped project and parent fields. Preserve
the existing project-scoped schema behavior by introducing or reusing a
team-specific compact setting schema for the teamSchema path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f8cccd78-1ea4-43a7-8385-c1aafac15b02

📥 Commits

Reviewing files that changed from the base of the PR and between 97ca60a and 8250d62.

📒 Files selected for processing (23)
  • docs/superpowers/plans/2026-07-27-asana-core-actions.md
  • docs/superpowers/specs/2026-07-27-asana-core-actions-design.md
  • src/providers/asana/actions-attachments.ts
  • src/providers/asana/actions-custom-fields.ts
  • src/providers/asana/actions-projects.ts
  • src/providers/asana/actions-stories-tags.ts
  • src/providers/asana/actions-tasks.ts
  • src/providers/asana/actions-teams.ts
  • src/providers/asana/actions-users.ts
  • src/providers/asana/actions-workspaces.ts
  • src/providers/asana/actions.ts
  • src/providers/asana/custom-field-metadata.ts
  • src/providers/asana/definition.ts
  • src/providers/asana/executors.ts
  • src/providers/asana/runtime-attachments.ts
  • src/providers/asana/runtime-custom-fields.ts
  • src/providers/asana/runtime-projects-sections.ts
  • src/providers/asana/runtime-stories-tags.ts
  • src/providers/asana/runtime-tasks.ts
  • src/providers/asana/runtime-workspaces-users-teams.ts
  • src/providers/asana/runtime.test.ts
  • src/providers/asana/runtime.ts
  • src/providers/asana/schemas.ts
💤 Files with no reviewable changes (1)
  • src/providers/asana/actions.ts

Comment thread docs/superpowers/plans/2026-07-27-asana-core-actions.md Outdated
@BlackHole1 BlackHole1 self-assigned this Jul 27, 2026
…arch

Upload external-URL attachments as `multipart/form-data`. Asana documents
`multipart/form-data` as the only accepted encoding for `POST /attachments`,
and its official SDKs send `parent`, `resource_subtype`, `url`, and `name` as
form fields, so the JSON data envelope would have been rejected. Both create
paths now share one `uploadAsanaAttachment` request seam.

Stop advertising a cursor for Asana endpoints that never return `next_page`.
`GET /workspaces/{workspace_gid}/projects/search` and
`GET /teams/{team_gid}/custom_field_settings` respond with `data` only, so
`search_workspace_projects` and `list_team_custom_field_settings` returned a
`nextCursor` that was always null and that no input could consume. A new
`listAsanaUnpaginatedResources` helper owns that shape and also replaces the
ad-hoc cursor stripping in `search_workspace_tasks`.
These working notes were only an artifact of building the provider. They also
carried a contributor's local machine paths, and nothing outside the directory
referenced them.
@BlackHole1
BlackHole1 merged commit 2409c98 into oomol-lab:main Jul 27, 2026
3 checks passed
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