# @kody/asana ## Intent Provide reusable, account-agnostic Asana helpers so Kody agents can read and update workspaces, projects, tasks, and stories/comments through a saved `asana` / `asana-*` OAuth integration or a personal access token — without hand-rolling REST. Mutations are previewable with `dryRun: true` and only run live after `confirm: true`. This listing is meant to be forked. After you fork, connect **your** Asana workspace. Do not treat the live `@kody/asana` package storage as yours. ## What it does - List or inspect workspaces, projects, tasks, and stories/comments - Create or update projects, tasks, and comments after explicit confirmation - Call an unwrapped Asana REST path through `./request` - Connect more than one Asana account via `integrationName` / `account` ## Prerequisites / setup Asana has **no built-in Kody OAuth app**. Choose one lane: | Lane | When to use | Credential | | --- | --- | --- | | **OAuth** (recommended) | Multi-account, refresh tokens, shared helpers | Saved integration `asana` or `asana-` | | **Personal access token** | Fastest for a single workspace / personal scripts | User secret `asanaPat` (or `asanaPat-`) | Both lanes send `Authorization: Bearer …`. Required API host: **`app.asana.com`**. Approve it in the account secrets UI. ### Lane A — BYO OAuth 1. Create an OAuth application at https://app.asana.com/0/my-apps 2. Set the redirect URI **exactly** to `https://kody.codes/connect/oauth` 3. Under **OAuth → Permission scopes**, enable the scopes this package uses (`workspaces:read`, `projects:read`, `projects:write`, `tasks:read`, `tasks:write`, `stories:read`, `stories:write`, `users:read`) or toggle **Full permissions** (`default`). 4. Connect while signed in to Kody: https://kody.codes/connect/oauth?provider=asana&authorizeUrl=https%3A%2F%2Fapp.asana.com%2F-%2Foauth_authorize&tokenUrl=https%3A%2F%2Fapp.asana.com%2F-%2Foauth_token&apiBaseUrl=https%3A%2F%2Fapp.asana.com%2Fapi%2F1.0&scopes=workspaces%3Aread%20projects%3Aread%20projects%3Awrite%20tasks%3Aread%20tasks%3Awrite%20stories%3Aread%20stories%3Awrite%20users%3Aread&flow=confidential&pkce=true&allowedHosts=app.asana.com&dashboardUrl=https%3A%2F%2Fapp.asana.com%2F0%2Fmy-apps 5. Paste the Asana client id and client secret into the Kody wizard (never into chat). Approve host `app.asana.com`. 6. Reconnect later with https://kody.codes/connect/oauth?provider=asana OAuth authorize URL: `https://app.asana.com/-/oauth_authorize`. Token URL: `https://app.asana.com/-/oauth_token`. Flow: confidential (client secret) plus S256 PKCE. Asana scopes are **space-separated**. To connect a second workspace, change `provider` (for example `provider=asana-work`) and pass `integrationName: 'asana-work'` on every call. ### Lane B — Personal access token 1. Create a token at https://app.asana.com/0/my-apps 2. Save it (do not paste the value in chat): https://kody.codes/account/secrets/new?name=asanaPat&description=Asana%20personal%20access%20token&allowedHosts=app.asana.com&scope=user For a second workspace/token, use a distinct secret name such as `asanaPat-work` and pass `secretName: 'asanaPat-work'` (or `account: 'work'`, which resolves to `asana-work` / `asanaPat-work`). ### Scopes | Scope | Needed for | | --- | --- | | `workspaces:read` | `./list-workspaces`, `./get-workspace` | | `projects:read` | `./list-projects`, `./get-project` | | `projects:write` | `./create-project` | | `tasks:read` | `./list-tasks`, `./get-task` | | `tasks:write` | `./create-task`, `./update-task` | | `stories:read` | `./list-stories` | | `stories:write` | `./create-story` | | `users:read` | `./viewer`, `./smoke-test` | | `default` | Full permissions when an endpoint has no granular scope | If Asana returns 401/403 or an insufficient-scope error, helpers throw a message that names the missing scope and the next setup URL (reconnect OAuth with that scope, or save a PAT). Agents: see [`AGENTS.md`](./AGENTS.md) for import paths, smoke checks, and mutation snippets. ## Done when - `asana` OAuth is connected or `asanaPat` is saved; host `app.asana.com` is approved - Smoke test returns `{ ok: true, live: true, … }` with a viewer gid (no email), or `{ ok: true, live: false }` plus setup URLs when credentials are missing - Mutations preview with `dryRun: true` and only run live with `confirm: true` after you approve the target workspace/project/task ## Branding The community icon is Asana's official three-dot logomark from [Asana brand](https://asana.com/brand) (the coral mark published in the horizontal lockup). Paths are unmodified. Asana® is a trademark of Asana, Inc. This package is not affiliated with or endorsed by Asana, Inc. ## Docs - [Asana REST API](https://developers.asana.com/docs/quick-start) - [OAuth](https://developers.asana.com/docs/oauth) - [OAuth scopes](https://developers.asana.com/docs/oauth-scopes) - [Personal access tokens](https://developers.asana.com/docs/personal-access-token)