Build product integrations with AI.
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(audit): check every event's metadata against the vocabulary (#7276) Make the metadata we record part of the contract instead of a free-form bag: `event.ts` already declared a shape per action, but `AuditSpec.metadata` returned `Record<string, unknown>` and the emit site cast it away, so none of it was ever checked. What we did: - `AuditEventTable` now carries the metadata each action may emit, so the vocabulary and the payload shape are one declaration. An action can't exist without a shape, and a shape can't be declared for an action that doesn't exist. - Deleted the `EmittedButNotInVocabulary` / `InVocabularyButNotEmitted` check: with one table there is nothing left to keep in sync. `AuditResourceAction` is derived from it. - The middleware and the MCP tools read the same lookup, so recording a key an action doesn't declare — or metadata for an action declared metadata-less — is a build error. `metadata.ts` moves to `@nangohq/types` alongside the table. - `auditConnection.ts` swaps its `as AuditEvent` cast for an annotation and gets checked for free. - Moved the remaining event types — `AuditEventCommon`, `AuditResourceAction`, `AuditEvent`, `StoredAuditEvent` — into `@nangohq/types` and deleted `packages/audit/lib/event.ts`. They were 56 lines of derivation sitting one package away from what they derive from, every import already coming from `@nangohq/types`. The audit contract is now in one place instead of split across two packages. - Added `.agents/skills/adding-audit-events/SKILL.md`, a runbook for covering a new endpoint. ## What turning it on found Six real divergences, all fixed here: - `billing.spend_alert_changed` recorded `thresholdInCents` and `integration.deleted` the provider, both against actions the contract declared metadata-less. The data was reaching ClickHouse with no read type describing it. - `function.deployed` promised a `FunctionSource` and recorded whatever the request sent. An unrecognised value now records as a repo deploy. - `integrationProviderMeta` and `auditTrailFilters` returned `Record<string, unknown>`, which let their call sites through unchecked. `IntegrationCreatedMetadata` is renamed `IntegrationProviderMetadata`, since `integration.deleted` uses the same shape and a `Created` type shouldn't describe a delete. The consolidation is worth more than tidiness: `@nangohq/types` cannot depend on `@nangohq/audit`, so while `AuditEvent` lived there, `api.ts` was structurally unable to reference it. Deriving `ApiAuditTrailEvent` from the same union is now a 3-call-site change rather than impossible — not done here. ## What it does not cover - **Presence.** Metadata fields are optional by design, so a spec that quietly stops recording `providerConfigKey` still compiles. The per-resource unit tests are what catch that. - **`auditSyncCommand`.** It picks its action at runtime from `req.body.command`, so checking it means constructing the event per action — a restructure, not a type change. - **The engine's cast.** `emit` sees `resource`/`action` widened, but the spec boundary already validated the metadata, so the cast only re-widens a checked value. - **A stray key alongside a valid one, on the MCP path only.** The tool audit has to be a union over the vocabulary because tools pass explicit type arguments to `defineManagementMcpTool` and `TResponse` isn't inferable — and excess-property checking against a union admits a key present in any member. A stray key on its own, a wrong type, and metadata on a metadata-less action are all caught. - **Which shape an action points at.** Nothing says `connection.updated` should carry `ConnectionUpdatedMetadata` rather than another shape. That stays a review judgement. ## Test plan - [x] `ts-build`, `lint`, `format:check` clean - [x] 1,082 server unit, 48 audit package unit, 46 audit integration — all unchanged - [x] Break-checked the enforcement: a stray key on a spec, and metadata on `integration.deleted` via MCP, each fail by name - [x] Break-checked the contract from both sides: adding or removing an action in the vocabulary fails twice — the derivation can't index, independently of any assertion - [x] Dry-ran the runbook: adding an action to the vocabulary alone fails in the webapp's filter list, so the step nobody remembers is compiler-enforced - [ ] After deploy: `metadata` on new events should be unchanged in shape; this is a type-level change with two behavioural exceptions, both narrowing what we record (`function.deployed` source, and nothing else) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 4 天前 | |
docs: replace mentions of secret key with API key (#7107) <!-- Describe the problem and your solution --> Follow-up to the Account API keys docs work (NAN-6569): replace leftover legacy “secret key” terminology across docs with Environment API key / API key language. - Prose and first-request examples now say **Environment API key** - Placeholders use `<NANGO-API-KEY>`; Node examples prefer `apiKey` - Dashboard “secret key” links now point to `/reference/backend/http-api/api-keys` - Preserved CLI `NANGO_SECRET_KEY_<ENV>`, provider Secret Key fields, changelog history, and the deprecated SDK `secretKey` alias - Follow-up commit fixed false positives (Huntress provider wording, placeholder hyphenation, leftover dashboard links) <!-- Issue ticket number and link (if applicable) --> https://linear.app/nango/issue/NAN-6569 <!-- Testing instructions (skip if just adding/editing providers) --> - [x] `mintlify broken-links` from `docs/` - [ ] Spot-check a provider first-request example (cURL + Node) - [ ] Spot-check security, functions CLI, sample app, and webhooks guides - [ ] Confirm CLI `.env` examples still use `NANGO_SECRET_KEY_DEV` / `NANGO_SECRET_KEY_PROD` - [ ] Confirm provider connect docs still say provider Secret Key / API Secret where appropriate Made with [Cursor](https://cursor.com) <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7107?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 20 天前 | |
chore(lint): replace ESLint with oxlint (#6604) ## Problem Final step of the ESLint → oxlint migration ([NAN-5769](https://linear.app/nango/issue/NAN-5769)). ESLint is slow on this monorepo (~77s full-repo, OOMs in CI, ~3–7s per file at pre-commit). The prerequisites are now merged — import sorting moved to Prettier (#6582) and tsconfigs made `typescript-go`-compatible (#6593) — so we can swap the engine. ## Solution Replace ESLint (and its 10 plugins) with **oxlint**, type-aware via `oxlint-tsgolint`. **Linting** - `.oxlintrc.json` replicates the existing ESLint rule set, type-aware enabled. Type-aware rules are scoped to TS files (off for `js/cjs/mjs`, matching the old config); `.d.ts` is ignored. - `lint` / `lint:fix` now run oxlint. The CI lint job drops the `ts-build --noCheck` step and the 8 GB heap workaround — `tsgolint` resolves types from source. - Removed `eslint`, `@typescript-eslint/*`, all `eslint-plugin-*`, `eslint-config-prettier`, `globals`; deleted `eslint.config.mjs`. **Formatting — now separate from linting (by design)** - ESLint used to run Prettier as a lint rule (`eslint-plugin-prettier`), so `eslint --fix` also formatted. oxlint deliberately does **not** format — it treats linting and formatting as separate concerns (same stance as Biome; ESLint itself has moved this way), and there's no equivalent plugin. - To keep formatting enforced and convenient: added a `format:check` script + CI step (formatting was previously only gated through `eslint-plugin-prettier`), and `lint-staged` now runs `oxlint --fix` **and** `prettier --write` on staged files. (The Prettier scripts are also renamed `prettier-format`/`prettier-check` → `format`/`format:check`.) - **DX impact:** formatting a file/repo by hand is now a separate `npm run format` rather than riding along with `lint:fix`. Commit-time formatting is unchanged (the hook still formats staged files), so this only affects manual runs. **Dropped rules** (no oxlint equivalent): `import/no-extraneous-dependencies`, `react/jsx-sort-props`, `@typescript-eslint/member-ordering`. (`import/order` already moved to Prettier in #6582.) Everything else carries over — including the design-system guardrail `react/forbid-component-props` (no `className`/`style` on `Button`/`IconButton`), which oxlint supports with the same config. One code site needed an explicit `url.href` — oxlint's `restrict-template-expressions` is stricter on URL objects. Docs (`AGENTS.md` / `CLAUDE.md`) updated for oxlint + the editor-extension requirement. Sub-issue: NAN-5811. ## Testing - `npm run lint -- --quiet` (oxlint, type-aware) exits 0 — the ~6.7k remaining items are `warn`-level rules (matching ESLint's warnings, suppressed by `--quiet` in CI) - `npm run format:check` exits 0; zero `tsconfig-error` diagnostics (type-aware is on via `options.typeAware` in `.oxlintrc.json` — no CLI flag needed) - CI `lint-code` job: ~58s (was ~149s with ESLint) | 2 个月前 | |
feat(ci): add Storybook PR preview deploys (#7084) ## Problem There's no stable place to share WIP components. Deploying Storybook from a feature branch overwrites `storybook.nango.dev`, and it gets clobbered again on the next `app_ui` merge to master. ## Solution - Every PR now gets its own Storybook at `pr-<N>-storybook.app-development.nango.dev`, uploaded to `previews/pr-<N>-storybook/` in the existing webapp preview bucket. - No infrastructure changes: the CloudFront viewer-request function already derives the S3 prefix from the first host label, and the wildcard cert, DNS, noindex header and 30-day lifecycle rule all cover the new host. No new Actions variables either — it reuses `PREVIEW_APP_UI_ROLE` / `_BUCKET` / `_DISTRIBUTION_ID`. - `preview-webapp.yml` is folded into `preview.yml` so all previews report into **one** sticky PR comment rather than one comment per preview. `comment-init` and `comment-final` are its only writers, avoiding the lost-update race two workflows editing one comment would hit. Adding a future preview is one more job plus one row. - The webapp and Storybook jobs run independently, so a broken story no longer blocks the webapp preview. - Shared logic extracted into `.github/actions/preview-comment` and `.github/actions/deploy-preview`. Fixes [NAN-6403](https://linear.app/nango/issue/NAN-6403) ## Testing - `npm run -w @nangohq/design-system build-storybook` passes; every file in `storybook-static/` ends in a simple extension, so the CloudFront function's extension-less → `index.html` branch only catches real routes. - `actionlint` clean on `preview.yml` (verified it actually validates the local composite-action inputs by re-running against a copy with a misspelled input — it caught it). - No required status check in the `master` ruleset references the old `preview` job name. - **Remaining:** this branch touches `.github/` only, so it doesn't match the path filter. A throwaway change under `packages/design-system/**` is needed to trigger a real run — then check one comment with both rows going 🔄 → ✅, a second commit updating that same comment, the Storybook manager and `?path=/docs/...` / `iframe.html?id=...` loading, `x-robots-tag: noindex` present, and `pr-<N>.app-development.nango.dev` still serving the webapp. | 21 天前 | |
fix(husky): skip prepare-commit-msg during rebase (#6168) ## Problem When running `git rebase` (and similarly `git cherry-pick`) HEAD is detached for each commit being replayed. The `prepare-commit-msg` hook calls `git symbolic-ref --short HEAD`, which fails for every replayed commit with: ``` fatal: ref HEAD is not a symbolic ref ``` The errors are harmless (the rebase still succeeds), but they pollute the output. The hook would also potentially mutate already-written commit messages during replay, which is not the intent of `prepare-commit-msg`. ## Solution Early-exit the hook when the repo is mid-rebase or mid-cherry-pick. Detection uses standard git markers under `$GIT_DIR`: - `rebase-merge/` — interactive and merge-based rebases - `rebase-apply/` — `git am` and `git rebase --apply` (legacy) - `CHERRY_PICK_HEAD` — cherry-pick in progress No `2>/dev/null` is used, so any *unexpected* failure of `git symbolic-ref` (corrupt repo, missing HEAD, etc.) will still surface during normal commits. ## Testing Verified by running the hook directly with a temp commit-msg file under each condition: - [x] Original script + detached HEAD + `rebase-merge/` → reproduces `fatal: ref HEAD is not a symbolic ref` (control) - [x] Fixed script + detached HEAD + `rebase-merge/` → exits 0, no output - [x] Fixed script + detached HEAD + `CHERRY_PICK_HEAD` → exits 0, no output - [x] Fixed script + normal state + non-`gh-` branch → message unchanged, exits 0 - [x] Fixed script + normal state + `gh-123-foo` branch → message prefixed with `[gh-123]`, exits 0 | 3 个月前 | |
Update readme | 3 年前 | |
feat: ingest usage events to clickhouse (#5798) This commit introduce clickhouse and ingest usage events to raw table It doesn't ingest connections or records usage because they are not event-based and I haven't figure out how I am gonna model those metrics yet. CLICKHOUSE_URL isn't set in staging/prod. Until then code is noop Next steps will be creating materialized views for the metrics. <!-- Describe the problem and your solution --> <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- Summary by @propel-code-bot --> --- This PR also establishes the foundational ingestion pipeline around ClickHouse by integrating migration and ingestion lifecycle handling into the metering flow and introducing buffered event processing so event-based analytics can be captured reliably without disrupting existing billing and usage-tracking paths. It formalizes the initial event-oriented ingestion scope as a staged rollout toward downstream metric modeling, while keeping behavior safely disabled in environments where ClickHouse is not configured. --- *This summary was automatically generated by @propel-code-bot* | 4 个月前 | |
docs: draft the agent sessions guide (NAN-6832) (#7317) NAN-6832 Adds a guide for agent sessions under Guides > Functions. Covers creating a session and what each request field does, how a session selects connections and resolves one per integration, the toolset and pinned tools, the meta tools, and the session MCP endpoint. Marked experimental. Session termination and expiry, nango_proxy, and session observability are left for NAN-6833. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7317?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Robin Guldener <r.guldener@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 1 天前 | |
fix(github-template): fix secret key access (#2662) ## Describe your changes Add the env so it can be picked up and check correctly for existence ## Issue ticket number and link ## Checklist before requesting a review (skip if just adding/editing APIs & templates) - [ ] I added tests, otherwise the reason is: - [ ] I added observability, otherwise the reason is: - [ ] I added analytics, otherwise the reason is: <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced new environment variables for managing secret keys in development and production stages. - **Improvements** - Enhanced clarity and security in the deployment process by streamlining the retrieval of secret keys. <!-- end of auto-generated comment: release notes by coderabbit.ai --> | 1 年前 | |
fix(syncs): batch schedule search fan-out (#7318) ## Problem The connection Syncs tab returns a 500 for any connection with more than 1000 syncs. `getSyncs` sends one schedule name per sync in a single `POST /v1/schedules/search`, and that route caps `names` at 1000, so the orchestrator answers 400 and `getSyncs` throws. Levity hit this in prod with 1581 syncs on one connection. The connections list fans out the same way but fails soft, silently dropping the "Schedule paused" badge whenever a page of 20 connections totals over 1000 syncs. ## Solution - Chunk inside `Orchestrator.searchSchedules` rather than at each call site, so `getSyncs`, `getConnections` and `manager.service` are all covered and a new caller cannot reintroduce the fan-out. - Move the cap to `maxScheduleNamesPerSearch` so the client and the route schema cannot drift. - Skip the orchestrator call entirely when a connection has no syncs. - Drop the unused `TestOrchestratorService` from the orchestrator's public exports: shared now imports the package at runtime, and the main entry was loading this dead test helper (and its scheduler test-db import) into every consumer. Raising the cap instead only moves the ceiling: the scheduler resolves these names with a single `whereIn`. Fixes [NAN-6818](https://linear.app/nango/issue/NAN-6818) ## Testing - Unit tests cover batch boundaries, merging across batches, a failing later batch, and the empty case. - Verified locally against a seeded connection with 1601 syncs: the tab now returns 200 with all 1601 rows, each carrying `schedule_status`. Probing the orchestrator directly confirms the boundary — 1000 names → 200, 1001 → 400. ## Follow-ups - The tab still fetches every sync with no pagination and re-polls every 5s — [NAN-6819](https://linear.app/nango/issue/NAN-6819). | 1 天前 | |
chore(kms): rename file (#7307) - Missed change from previous PR - Rename file <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7307?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 2 天前 | |
feat(integrations): add support for scrollstash-mcp (#7282) ## Describe the problem and your solution - add support for scrollstash-mcp <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7282?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 2 天前 | |
feat(logs): add OpenSearch backend selectable via NANGO_LOGS_PROVIDER (#5873) Wire @opensearch-project/opensearch client, ISM policies, shared mappings, and isLogsNotFoundError for API handlers. Made-with: Cursor <!-- Describe the problem and your solution --> <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> | 3 个月前 | |
docs: Rename docs-v2 to docs (#4855) Change name of the root folder for docs <!-- Summary by @propel-code-bot --> --- **Rename Documentation Root Directory from `docs-v2` to `docs`** This pull request renames the root documentation directory from `docs-v2` to `docs` and updates all internal references accordingly. The update is a structural change that standardizes the main documentation folder and all internal edit/contribution links, ensuring consistency across the project. No documentation content or code has been changed except for the updated references and reorganization. <details> <summary><strong>Key Changes</strong></summary> • Renamed documentation root directory from `docs-v2` to `docs`. • Updated all documentation files and internal edit/contribution links to point to the new `docs/` directory. • Reorganized the docs structure so that all files and subdirectories previously under `docs-v2/` now reside under `docs/`. • Adjusted any hard-coded paths within markdown files (e.g., edit/contribution links) from `docs-v2` to `docs` throughout the documentation. </details> <details> <summary><strong>Affected Areas</strong></summary> • `docs-v2/` (now renamed to `docs/`) • All documentation markdown (`.mdx`) files referencing the docs root folder • Paths within contribution, edit, and helper links in documentation • Any tooling, scripts, or integrations that rely on the previous docs path (potentially in CI, build pipelines, or static site generators) </details> --- *This summary was automatically generated by @propel-code-bot* | 10 个月前 | |
[gh-#1139] Add OAuth to Gong API (#1140) * Add OAuth to Gong API * Fix docs * Fix yaml indentation | 2 年前 | |
fix(runner): auth runner start (#7288) ## Summary - Require a jobs identity on runner `start` / `abort` / `notifyWhenIdle` when `NANGO_INTERNAL_AUTH_REQUIRED=true`. Jobs mints an EdDSA JWT (`aud: runner`); runners verify with a public key only. - Jobs never puts a minting secret on the runner. At node start it injects the Ed25519 public key, a jobs-audience node JWT, and a snapshot of `REQUIRED`. `/health` stays open. - Default is a no-op. Existing runners keep accepting dispatch (fail-open). Enforcement starts on pods created after jobs has a signing key and `REQUIRED=true`. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 2 天前 | |
feat(webapp): Add design system tokens sync (#6201) ## Problem The webapp redesign requires a new design system with tokens authored in Figma via Tokens Studio. There was no pipeline to get those tokens into code, and no way for the designer to share tokens across multiple Figma files. ## Solution Adds a `packages/design-system` package with a token sync workflow: - **Designer** edits tokens in Figma (Tokens Studio plugin) → pushes to the `design/tokens` branch via Figma plugin - **Developer** runs `npm run tokens:fetch` → fetches `tokens.json` from that branch → regenerates CSS → commits both files No env vars or Figma API credentials required — the repo is public and tokens are fetched via a plain GitHub raw URL. **`packages/design-system` contains:** - `tokens/tokens.json` — Tokens Studio export (committed to git) - `tokens/tokens.generated.css` — generated CSS: primitives (`:root`, `--ds-` prefix), semantic light/dark (`:root` / `[data-theme="dark"]`), and a Tailwind v4 `@theme` block for utility class generation (`bg-surface-canvas`, `text-text-strong`, etc.) - `scripts/tokens-fetch.mjs` — token pipeline using Style Dictionary v5 + sd-transforms - Unit tests for all pipeline functions (`tokens-fetch.unit.test.mjs`) The CSS is imported in `packages/webapp/src/index.css` and picked up by Vite's HMR — token changes in `tokens.generated.css` propagate to the browser instantly without a page reload. The new tokens are additive — legacy `--color-*` vars in `index.css` are untouched. Primitives use `--ds-` prefix to avoid collisions. Dark mode via `[data-theme="dark"]`. High level Notion doc describing the integration at https://www.notion.so/nangohq/Figma-Design-Tokens-integration-367ce298312180d2a563f5b43c5a16ce **New tokens are not yet used for any UI, that will happen in follow ups.** Fixes [NAN-5664](https://linear.app/nango/issue/NAN-5664) ## Testing - `cd packages/design-system && npm run tokens:fetch` — fetches tokens from GitHub `design/tokens` branch, writes `tokens.json` and `tokens.generated.css` - `npm run tokens:build` — rebuilds CSS from local `tokens.json` (no network) - `npm test` — runs unit tests for the pipeline script - Verified in local dev: token changes in `tokens.generated.css` hot-reload in the browser via Vite HMR; the full pipeline (`tokens.json` → `tokens:build` → CSS → HMR) works end-to-end <!-- start telescope-canary-packages --> <!-- end telescope-canary-packages --> | 3 个月前 | |
feat(types): enforce audit coverage via an endpoint opt-out policy (NAN-6269) (#6916) - Introduces `ApiEndpoint<>`, a customer-facing endpoint type with a **required** `Audit` field, making audit coverage a compile-time decision: a private/public API endpoint no longer compiles until it declares either the audit event it records or an explicit `NoAuditEvent` opt-out with a reason. Internal-service endpoints (persist, jobs, orchestrator, …) keep the unchanged `Endpoint<>` type. - Annotates all 177 customer endpoints: 3 opt-ins to the already-wired events (connection deleted ×2, member role changed), 68 `TODO: audit coverage pending` (the control-plane worklist), 101 `non-auditable`, and 5 MFA endpoints `to be discussed`. ### Notes - This enforces the *declaration* of an audit policy per endpoint. Reconciling each declared policy against the `auditable()` middleware actually wired in the server is a planned follow-up. - MFA state-changing endpoints are parked as `to be discussed` — decision tracked in NAN-6450. - `UpdateOtlpSettings` appears unreferenced in the codebase; left annotated pending confirmation it isn't dead. ## Test plan - [x] `tsc -b` clean: types, server, webapp, connect-ui, persist, jobs - [x] Enforcement verified — removing an endpoint's `Audit` field fails to compile - [x] prettier + oxlint clean (only pre-existing `any` warnings in `Endpoint`) - [ ] Work through the `TODO: audit coverage pending` endpoints as part of audit coverage (NAN-6444) - [ ] Decide MFA endpoints (NAN-6450) - [ ] Confirm or remove `UpdateOtlpSettings` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/6916?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> | 1 个月前 | |
chore: harden npm installs (#6226) Adds a repository `.npmrc` that disables npm lifecycle scripts by default and blocks git/file/remote dependency fetches. Updates trusted publish flows to opt back into package lifecycle scripts so existing `prepublishOnly` build and copy steps still run during releases. Can't apply a seven-day release-age gate since that is part of new npm version. NAN-5581 | 3 个月前 | |
chore(cli): Bump node version (#6253) | 3 个月前 | |
feat(design-system): lift Tooltip into design system (#7176) ## Problem `Tooltip` lived in `packages/webapp/src/components/ui/Tooltip.tsx` and couldn't be consumed from `@nangohq/design-system` — the last high-traffic overlay primitive still in the webapp after `Dialog`, `Card`, `Badge` and `Alert`. It had also drifted from its [Dharma source](https://www.figma.com/design/T8aoiWC73uCiM5eucb0syk/Nango-%E2%80%94-Design-System--Dharma-?node-id=3-134595), which models an inverse chip. We rendered a light-grey panel on webapp-only utilities (`text-s`, `shadow-md`). Current shadcn ships the inverse look too, so the drift is ours. ## Solution - New `packages/design-system/src/components/ui/tooltip.tsx` at Figma parity — inverse chip, `rounded-ds-xs`, `px-1.5 py-1`, `type-label-sm`, `max-w-96`, `shadow-container-panel`. Every value maps to an existing token, so no `tokens:fetch`. - Dropped the `primary`/`secondary` pair — Figma ships one look, and `secondary`'s single call-site went pure black in dark mode. No variant axis left, so the component drops `cva`. - `Tooltip` no longer self-wraps in a `TooltipProvider`, which shadowed anything a consumer configured. The root provider in `providers.tsx` already defaults `delayDuration` to 0, so hover timing is unchanged. - Links inside a tooltip take the chip's own foreground with an underline, by redefining the link colour tokens in scope so every state follows. The accent tokens are tuned for the page surface and collapse on the inverted chip — down to 1.64:1 when pressed. A deliberate stopgap for the 12 links across 5 files; [NAN-5464](https://linear.app/nango/issue/NAN-5464/solve-issue-with-inaccessible-upgrade-link-in-tooltips) removes the links and these overrides together. - Moved `@radix-ui/react-tooltip` to the design system, migrated all 16 call-sites, deleted the webapp component. `InfoTooltip`, `ConditionalTooltip` and `PermissionGate` stay in the webapp — no Dharma source. - Dropped the Team members tooltip — its copy described the table directly beneath it, so the help icon earned nothing. - Locked `className`/`style` on `TooltipContent`. Four overrides that fought the new spec are deleted; the two keeping tooltip content hoverable carry a justified disable. Fixes [NAN-6676](https://linear.app/nango/issue/NAN-6676/lift-tooltip-into-the-design-system) ## Testing `ts-build`, `lint`, `format:check` and `build-storybook` clean. **[Visual QA checklist](https://app.notion.com/p/3c2ce2983121819ca9a4ccc6fa1a85bc)** — 8 surfaces on the [app preview](https://pr-7176.app-development.nango.dev), each in both themes. Four are ticked; the rest are open. New stories, replacing the deleted `App Components/UI/Tooltip`: [Sides](https://pr-7176-storybook.app-development.nango.dev/?path=/story/design-system-components-tooltip--sides) · [Alignment](https://pr-7176-storybook.app-development.nango.dev/?path=/story/design-system-components-tooltip--alignment) · [Long Content](https://pr-7176-storybook.app-development.nango.dev/?path=/story/design-system-components-tooltip--long-content) · [On Hover](https://pr-7176-storybook.app-development.nango.dev/?path=/story/design-system-components-tooltip--on-hover) ## Follow-ups - [NAN-6679](https://linear.app/nango/issue/NAN-6679/make-per-model-sync-breakdowns-discoverable-in-the-syncs-table) — `SyncsTab`'s two `SimpleCodeBlock` tooltips read as a frame around a code panel; they should be a popover behind a real trigger. - [NAN-5464](https://linear.app/nango/issue/NAN-5464/solve-issue-with-inaccessible-upgrade-link-in-tooltips) — now carries the full inventory of all 12 links in tooltips. Removing them retires both `pointer-events-auto` disables and the inverse-link rule added here. - The Figma Tooltip's optional `KbdGroup` comes from the old `CURRENT 🐺` library, not Dharma — skipped, worth cleaning up in the Figma file. - Ad-hoc hover hints (native `title=`) adopting the DS `Tooltip` — separate ticket under Component consolidation. | 11 天前 | |
feat(usage): CH-backed /plans/billing-usage (dev-gated, foundations for shadowing) (#6286) ## Summary - **Dev-only ClickHouse read path for the billing dashboard.** Gated behind `ALLOW_OVERRIDE_GETUSAGE_SERVICE` (env, off in prod) + a per-request `source=clickhouse|orb` query param. Default everywhere stays Orb; only opted-in sessions hit CH. Lays the groundwork to start shadowing the Orb read in dev, then graduate to production once the contract holds and CH ingestion has stabilized. - **Two new single-metric CH primitives.** `Clickhouse.getDailyCounter` (5 counter metrics: proxy, function_executions, function_logs, function_compute_gbms, webhook_forwards) and `Clickhouse.getDailySumAndBatches` (the 2 AVG metrics: records, connections). The AVG one returns per-day (sum, batches) so the running period average can be reconstructed exactly — per-day averages alone can't recombine when batch counts differ across days. The server-side formatter `toRunningAvgUsage` does that walk and emits `view_mode='cumulative'`. - **New contract on `/plans/billing-usage`.** Querystring gains `source`, `metrics=<csv>` (subset scoping), `breakdown[<metric>]=<dim>` (per-metric top-N + 'rest', cap 25), and `top=<N>`. `BillingUsageMetric` gains an optional `breakdown` array; when breakdown is requested for a metric, top-level `usage`/`total` are empty and only `breakdown` carries data (mutually exclusive by design). ## Why dev-only for now The CH ingestion pipeline (S3 export → Orb) and the read primitives need shadowing time before they can drive billing-impacting decisions. This PR is the read side of that foundation: - Default routing is unchanged — Orb continues to serve every request unless a developer explicitly flips `localStorage('nango.billingUsageSource') = 'clickhouse'` AND the env gate is on. - Capping (`UsageTracker.getBillingMetrics`) continues to use Orb regardless of the gate; only the dashboard read path is wired to CH. - No silent Orb fallback on CH errors — regressions surface immediately in dev rather than being masked. ## Implementation notes - Per-metric dimension whitelist (`BREAKDOWN_DIMENSIONS`) is a single typed const in `packages/usage/lib/clickhouse/clickhouse.query.ts`; both the CH query types and the controller validator derive from it. - Top-N + 'rest' breakdown is always bounded by the CH SQL (`top_dims` CTE + `IF` partition); for AVG the per-dim `batches` is the global per-day count so per-series running averages remain additive to the no-dim global. The rollup bucket is signalled out-of-band via an `isRest` column on the wire so a real dim value literally named `'rest'` (a `connection_id`, `model`, `integration_id`, …) is never silently merged with the long-tail rollup. - Telemetry: `nango.billing.usage.clickhouse.query.duration_ms` distribution metric with `{ metric, breakdown, success }` tags, emitted by both CH read methods. Linear: https://linear.app/nango/issue/NAN-5724 Perf doc: https://linear.app/nango/document/clickhouse-metering-read-queries-72ca56b0ab7c ## Benchmark — shipping SQL vs perf doc The perf doc validated a slightly simpler SQL shape (no `global_batches` CTE on the AVG side, single `IN (SELECT)` on the counter side). The shipping SQL adds an extra scan on AVG (for additive-to-global per-dim batches) and a second `IN (SELECT)` on counters (for the `isRest` collision fix). Re-ran the exact perf-doc accounts/window with the shipping SQL to quantify the delta: **AVG, doomsday-fn (3660), 14-day window** — the doc's worst case: | Dim | Doc bench (ms) | Shipping (ms) | Δ wall | Δ read_rows | |---|---|---|---|---| | environment_id | 1534 | 1607 | **+5%** | +50% (59M → 89M) | | integration_id | 1608 | 1653 | **+3%** | +50% | | connection_id | 2958 | 2868 | **−3%** (noise) | +50% | | model | 1709 | 1817 | **+6%** | +50% | **The +50% read_rows from the extra scan does not translate to +50% wall time.** CH parallelizes the third scan across cores; bottleneck on these cells is the per-(day, dim) aggregation, not the scan. All other accounts (small/medium/large/doomsday-px) land equal-or-faster than the doc bench across all AVG dimensions. **COUNTER side**: shipping is equal-or-faster across all 5 buckets. Doomsday-fn function_executions: 392 → 394ms (within noise). The two `IN (SELECT dim FROM top_dims)` calls — one for `dimensionValue`, one for `isRest` — are CSE'd to a single hash-set lookup by CH's planner. **Conclusion**: shipping SQL is within the perf doc's published numbers across every account × dimension cell. Worst-case dashboard click stays ~3s for doomsday-fn records-by-connection_id, same as the doc. The monthly multi-dim MV optimization from the doc still applies and would cut this to ~1.9s. ## Test plan - [x] CH integration test for `getDailyCounter` (no-dim, with dimension, single-day, multi-metric coverage incl. `function_*` quantity selectors) — passes against testcontainer. - [x] CH integration test for `getDailySumAndBatches` (records / connections, with and without dimension, timeframe-filter check, additivity-to-global with an inactive dim, rollup-vs-real-`'rest'`-value collision) — passes. - [x] Unit tests for `toRunningAvgUsage` (worked example, per-dim additivity, ordering, float quantity, low-volume breakdown does NOT round to 0, edge cases) and `toCounterBillingMetricSeries` (rollup carries `isRest`, real `'rest'` value distinguished from rollup). - [x] Controller integration test (real Postgres + CH testcontainers, real HTTP, only Orb-external `billing.getCustomer` mocked) covering the env gate on/off, source override, metrics scoping, breakdown contract (top-N + 'rest', schema rejection, empty-breakdown 400, top clamp), and the breakdown-only-response shape (top-level `usage: []` / `total: 0` when breakdown requested). - [x] Bench shipping SQL against the perf doc's accounts/window — within published numbers (see above). - [ ] Deploy to dev, flip `localStorage('nango.billingUsageSource') = 'clickhouse'`, walk every metric panel + drilldown, compare numbers against the Orb-served view side by side. - [ ] Watch `nango.billing.usage.clickhouse.query.duration_ms` p95 in dev for a few days before shadowing. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 3 个月前 | |
chore(lint): move import sorting to Prettier (#6582) ## Problem We're replacing ESLint with oxlint (NAN-5769). oxlint has no `import/order` equivalent — its maintainers deliberately defer import sorting to the formatter — so import ordering needs a new home before the linter swap. ## Solution Move import ordering to Prettier via `@ianvs/prettier-plugin-sort-imports`, configured to replicate the existing `import/order` grouping exactly: builtins → external → `@nangohq/*` → `@/*` + relative → type imports, blank lines between groups, alphabetised within. The `import/order` rule (and its now-pointless migrations override) is removed from the ESLint config. Doing this first — while ESLint still runs — means the change is verifiable in isolation: format-on-save behaviour is identical for developers, and CI's existing `prettier --check` + ESLint both still gate it. Two commits: - `chore(lint): move import sorting to Prettier` — the plugin + config (this is the one to actually review) - `style: sort imports across the codebase` — the mechanical 489-file reformat (skim only; import order changes only, no logic) Part of NAN-5769. Sub-issue: NAN-5808. ## Testing - `eslint . --quiet` passes clean (exit 0) on the reformatted code - Reformat is purely mechanical — only import grouping/order changed - Spot-checked plugin output against the old `import/order` grouping; identical | 2 个月前 | |
[NAN-457] document script model introspection endpoint (#1765) ## Describe your changes Alias flow/configs to `scripts/config` to better naming and update docs ## Issue ticket number and link NAN-457 ## Checklist before requesting a review (skip if just adding/editing APIs & templates) - [ ] I added tests, otherwise the reason is: - [ ] I added observability, otherwise the reason is: - [ ] I added analytics, otherwise the reason is: | 2 年前 | |
chore(lint): replace ESLint with oxlint (#6604) ## Problem Final step of the ESLint → oxlint migration ([NAN-5769](https://linear.app/nango/issue/NAN-5769)). ESLint is slow on this monorepo (~77s full-repo, OOMs in CI, ~3–7s per file at pre-commit). The prerequisites are now merged — import sorting moved to Prettier (#6582) and tsconfigs made `typescript-go`-compatible (#6593) — so we can swap the engine. ## Solution Replace ESLint (and its 10 plugins) with **oxlint**, type-aware via `oxlint-tsgolint`. **Linting** - `.oxlintrc.json` replicates the existing ESLint rule set, type-aware enabled. Type-aware rules are scoped to TS files (off for `js/cjs/mjs`, matching the old config); `.d.ts` is ignored. - `lint` / `lint:fix` now run oxlint. The CI lint job drops the `ts-build --noCheck` step and the 8 GB heap workaround — `tsgolint` resolves types from source. - Removed `eslint`, `@typescript-eslint/*`, all `eslint-plugin-*`, `eslint-config-prettier`, `globals`; deleted `eslint.config.mjs`. **Formatting — now separate from linting (by design)** - ESLint used to run Prettier as a lint rule (`eslint-plugin-prettier`), so `eslint --fix` also formatted. oxlint deliberately does **not** format — it treats linting and formatting as separate concerns (same stance as Biome; ESLint itself has moved this way), and there's no equivalent plugin. - To keep formatting enforced and convenient: added a `format:check` script + CI step (formatting was previously only gated through `eslint-plugin-prettier`), and `lint-staged` now runs `oxlint --fix` **and** `prettier --write` on staged files. (The Prettier scripts are also renamed `prettier-format`/`prettier-check` → `format`/`format:check`.) - **DX impact:** formatting a file/repo by hand is now a separate `npm run format` rather than riding along with `lint:fix`. Commit-time formatting is unchanged (the hook still formats staged files), so this only affects manual runs. **Dropped rules** (no oxlint equivalent): `import/no-extraneous-dependencies`, `react/jsx-sort-props`, `@typescript-eslint/member-ordering`. (`import/order` already moved to Prettier in #6582.) Everything else carries over — including the design-system guardrail `react/forbid-component-props` (no `className`/`style` on `Button`/`IconButton`), which oxlint supports with the same config. One code site needed an explicit `url.href` — oxlint's `restrict-template-expressions` is stricter on URL objects. Docs (`AGENTS.md` / `CLAUDE.md`) updated for oxlint + the editor-extension requirement. Sub-issue: NAN-5811. ## Testing - `npm run lint -- --quiet` (oxlint, type-aware) exits 0 — the ~6.7k remaining items are `warn`-level rules (matching ESLint's warnings, suppressed by `--quiet` in CI) - `npm run format:check` exits 0; zero `tsconfig-error` diagnostics (type-aware is on via `options.typeAware` in `.oxlintrc.json` — no CLI flag needed) - CI `lint-code` job: ~58s (was ~149s with ESLint) | 2 个月前 | |
chore(release): 0.71.6 | 2 天前 | |
chore: add repo agent guidance and skills (#6235) <!-- Describe the problem and your solution --> - Adds minimal root `AGENTS.md` setup guidance and repo-local skills for database migrations and UI visual debugging. - Updates the skill-creation guidance to remove Claude-specific wording so it can apply to agents generally. - Add DB migrations skill from @pfreixes PR https://github.com/NangoHQ/nango/pull/5923/changes - Add a UI debugging skill <!-- Issue ticket number and link (if applicable) --> NAN-5706 | 3 个月前 | |
docs: update external contribution guidelines (#6944) ## Problem and solution External contribution scope was too broad and we were being hit by PRs with improvements we didn't want to maintain, or completely new features. This PR updates the guidelines to limit accepted external pull requests to security fixes and new API support, routes other requests to GitHub issues or Slack. ## Issue [EPW-6](https://linear.app/nango/issue/EPW-6/stop-accepting-external-contributions) <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/6944?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Robin Guldener <r.guldener@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> | 1 个月前 | |
docs: update external contribution guidelines (#6944) ## Problem and solution External contribution scope was too broad and we were being hit by PRs with improvements we didn't want to maintain, or completely new features. This PR updates the guidelines to limit accepted external pull requests to security fixes and new API support, routes other requests to GitHub issues or Slack. ## Issue [EPW-6](https://linear.app/nango/issue/EPW-6/stop-accepting-external-contributions) <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/6944?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Robin Guldener <r.guldener@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> | 1 个月前 | |
fix(dockerfile): fix vulns in image (#7351) ## Summary - Upgrade Debian packages in the final image so `libgnutls30` picks up DSA-6281 (`3.7.9-2+deb12u7`). - Purge `perl-base` after apt work. Bookworm has no fix for the scanner-flagged CRITICAL/HIGH perl CVEs, and the Node runtime never uses Perl. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7351?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 1 天前 | |
fix(docker): cleanup (#3838) ## Changes - Deleted: server docker image - Changed: self-hosted docker image is using the main docker image as a source The main benefit is that it compiles in just a few secs now - Changed: self-hosted docker image is tagged with the version This means the version is rolling until we release another one - Added: error reporting in UI Just because I realised it was missing from the migration to vite | 1 年前 | |
v0.3: Rewrite (details in desc) commit b9cf3a62237a78c1067ca1d72a633a6e7d1a0525 Merge: 76ee2d8 387f791 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Tue Nov 29 16:36:18 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 commit 76ee2d89914ca0ca90836717a4905ca9b628f614 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Tue Nov 29 16:36:15 2022 +0100 Bug fixes commit 610a5b7d36e8faafc53a2942a5df38bd4a0a0b03 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Tue Nov 29 10:24:19 2022 +0100 Small fixes commit 387f791f0214ee2002a11985b114f8c5e41ff701 Author: Robin Guldener <r.guldener@gmail.com> Date: Mon Nov 28 20:03:37 2022 +0100 Adding Intuit, Monday.com and Dropbox templates commit e2e0437ddc183dfad7a5a5671bd7a706e783374c Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Mon Nov 28 15:22:47 2022 +0100 API changes commit f1d107db9f673abe5fbd27bd2eeedfe18b09b6e4 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Mon Nov 28 14:00:42 2022 +0100 Change node SDK package name commit d9df3c3782448892902f9c7e8a8125ceb2a343d0 Merge: b85fcfd 7d50475 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Mon Nov 28 12:21:07 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 # Conflicts: # packages/node-client/lib/index.ts commit b85fcfdb447a3d17300c426a9ec0bcc2638576c6 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Mon Nov 28 12:18:34 2022 +0100 Name refactor commit 7d50475d560495f202772477692388460572a13f Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 17:32:20 2022 +0100 Updated backend node SDK commit 780930e1c4776c5ed2ff4d9feadadcd979daaa1c Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 16:45:17 2022 +0100 Node SDK + modify cli commands commit 5f8de1c3ff86fc75090c6b112efa3e4cc96de0f0 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 16:25:18 2022 +0100 Remove raw_response column from Connection model commit 3be323020ad015d21a0aeeefab7afbd20143055f Merge: 11fbedd 19c7b39 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 16:21:26 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 commit 11fbeddc099390248101a52781cedc1d879adad6 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 16:21:19 2022 +0100 Refresh token if needed commit 19c7b39849c293fdc8a2798b6431078448f1935a Merge: 6ee867d 708c95e Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:46:47 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 commit 6ee867daf098797b48165f0f0c22e631af013cd6 Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:46:43 2022 +0100 Fix typos commit 708c95e61f8522666a96048a27423e410afb8c20 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 15:46:12 2022 +0100 Handle custom scope separator commit 5b14471a6a9dc4197401435100f4a2805e2dd528 Merge: 29592f2 5d2cced Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 15:27:14 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 commit 29592f21101fca98d860b4b2db98a5319d7b50b6 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 15:26:09 2022 +0100 Add blueprints commit 5d2ccedc9ab697a1e6d8342d54537414b774c7b2 Merge: 44d32b7 fb7d7a8 Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:25:54 2022 +0100 Merge branch 'v0.3' of https://github.com/NangoHQ/Pizzly into v0.3 commit 44d32b7e8ad72900966c66d9d5a8a64710ffad0e Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:16:55 2022 +0100 Add .env for Pizzly, change env variables to SERVER_HOST and SERVER_PORT commit fb7d7a8c91e8a5fbf280784ee106b96f05b000dc Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:16:55 2022 +0100 Add .env for Pizzly, change env variables to SERVER_HOST and SERVER_PORT commit 294a3c20696bfeca5638a1b3d10f357005bf0a70 Author: Robin Guldener <r.guldener@gmail.com> Date: Fri Nov 25 15:08:41 2022 +0100 Fix class name in frontend sample commit a3229b086e31e30b18d00530480d7703b1797dfc Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 14:25:25 2022 +0100 Improve CLI commit c598274b771bdf5bd4317266b9882b3267d0e9da Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 12:42:38 2022 +0100 Implement CLI commit b955b029a6ffa0113ba2bc7274f702484c8396f2 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 11:55:43 2022 +0100 Clean tsconfig files commit 746f0427b4c2a4d228c84437918105f2adf9919a Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 11:51:36 2022 +0100 Restructure files commit 8b5b4cdbe224aba664e63712b81bb6f0cbfd57b6 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Fri Nov 25 11:46:06 2022 +0100 Add routes/controllers/services for Connections & Configs commit c72651009c276aad1a474f986d3abfeeda7abc16 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 16:30:35 2022 +0100 Refactor commit ecc588739e56b6040052738badaebbea90c0cf35 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 16:18:19 2022 +0100 Restart server if db not ready commit 9eea8b5ea4061e60dded992bbc5088bdd71f131f Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 16:14:34 2022 +0100 Run Docker successfully commit 7959701eb22cd19d5b21ab7a110d2200b5bf82ee Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 15:53:14 2022 +0100 Refactor Integration model commit daab93c506fbff62d48a6c59b3770e0a8bce1773 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 15:11:00 2022 +0100 Refactor server commit 4f9bda9fdbf1da84b2375344c18b981160aa20d6 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Thu Nov 24 14:32:37 2022 +0100 Successful test of OAuth 1 and 2 commit cdc58987737ed29ad11ab89ce32fe2bd5b9314a2 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Wed Nov 23 22:22:41 2022 +0100 Run successfully commit 4c91c9c85d62a6e985c30661e2d11e277d480f8e Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Wed Nov 23 21:45:50 2022 +0100 DB support + models + restructure commit e03b92a9b8053f774c09525a6cec49aa2c9b8ce4 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Wed Nov 23 15:15:07 2022 +0100 Fix all errors commit 005ab3f34a3ebdc11c01d90d3f5e3d517e036f3f Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Wed Nov 23 11:28:26 2022 +0100 Add new Oauth code commit 94c33f947e0e9658d493d467ba24cc6aca4e4cd0 Author: Bastien Beurier <bastienbeurier@gmail.com> Date: Wed Nov 23 10:38:07 2022 +0100 Initial setup for Pizzly 0.3.0 | 3 年前 | |
Update short license | 3 年前 | |
docs: update API count from 800+ to 900+ (#6834) ## Changes **README (`README.md`)** — 5 references: tagline, nav link, "What is Nango?" intro, Auth section, and the auth callout. **Docs** - `docs/integrations/overview.mdx` — "All APIs & integrations" card - `docs/getting-started/intro-to-nango.mdx` — intro paragraph - `docs/getting-started/quickstart.mdx` — manual quickstart - `docs/guides/auth/auth-guide.mdx` — overview + auth-schemes capability (2 refs) - `docs/integrations/contribute-or-request-api.mdx` — reference to the nav group name - `docs/docs.json` — nav group label ("900+ APIs & Integrations") - `docs/llms-full.txt` — regenerated via `npm run docs:generate:llms` ## Left unchanged (intentional) Historical/dated records that describe past state are **not** retroactively edited: - `docs/updates/changelog.mdx` (past changelog entries) - `CHANGELOG.md` (release note: "update API count from 700+ to 800+") <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/6834?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> | 1 个月前 | |
chore(security): add SECURITY.md (#6255) <!-- Describe the problem and your solution --> <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> | 3 个月前 | |
chore(release): improvements (#2179) ## Describe your changes Fixes NAN-993 - Remove skip ci to build image even on release - Add GitHub author - Use proper version tag (with a `v`) | 2 年前 | |
feat(connect-ui): non-root base path via relative base + runtime basepath (#6802) ## Problem Connect UI's built assets are referenced from the domain root (`/assets/…`), so self-hosters serving it under a path prefix (e.g. `example.com/nango/connect/`) get 404s and a blank page. Replaces #6765, which rewrote `dist` in place at container startup — that required a writable `dist` at runtime and left the artifact broken until the rewrite ran. ## Solution The same prebuilt bundle now works under any base path: nothing is baked in at build time, there is no rewrite step, and read-only filesystems work. - Build with Vite `base: './'` so assets resolve relative to the document URL. - Derive the router basepath from `document.baseURI` at load. - Self-heal a slashless URL (`…/connect` → `…/connect/`) via an `onerror` retry on the entry script — fires only when the asset load actually failed. - Add `-s` (SPA fallback) to `serve:unsafe` so deep-route refreshes serve `index.html`. - Normalize the trailing slash wherever Nango produces a Connect UI URL: server links (new `buildConnectUiSessionLink` in utils), the frontend SDK iframe, and the dashboard preview iframe. - Send both the verbatim and trailing-slash forms of `NANGO_PUBLIC_CONNECT_URL` in the CSP (exact match for older SDKs, prefix match for assets and routes). - Fix two latent origin bugs that break any sub-path deployment: telemetry CORS and the dashboard preview compared the path-less browser `Origin` against the full URL. Fixes [NAN-6242](https://linear.app/nango/issue/NAN-6242) ## Testing - Browser e2e behind a prefix-stripping proxy: sub-path entry, slashless recovery (query preserved), deep-route refresh, and root deployment all boot with assets 200. - Unit and browser tests cover basepath derivation, link building, and the router under a basepath; build inspection confirms relative asset refs. ## Notes for self-hosters - The reverse proxy must strip the base path prefix before forwarding. - Custom static hosts need SPA fallback (rewrite unknown paths to `index.html`) if anyone does this at the moment — Nango's own static server and cloud CDN already have it. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 1 个月前 | |
chore: update version in manifest | 1 天前 | |
fix(syncs): batch schedule search fan-out (#7318) ## Problem The connection Syncs tab returns a 500 for any connection with more than 1000 syncs. `getSyncs` sends one schedule name per sync in a single `POST /v1/schedules/search`, and that route caps `names` at 1000, so the orchestrator answers 400 and `getSyncs` throws. Levity hit this in prod with 1581 syncs on one connection. The connections list fans out the same way but fails soft, silently dropping the "Schedule paused" badge whenever a page of 20 connections totals over 1000 syncs. ## Solution - Chunk inside `Orchestrator.searchSchedules` rather than at each call site, so `getSyncs`, `getConnections` and `manager.service` are all covered and a new caller cannot reintroduce the fan-out. - Move the cap to `maxScheduleNamesPerSearch` so the client and the route schema cannot drift. - Skip the orchestrator call entirely when a connection has no syncs. - Drop the unused `TestOrchestratorService` from the orchestrator's public exports: shared now imports the package at runtime, and the main entry was loading this dead test helper (and its scheduler test-db import) into every consumer. Raising the cap instead only moves the ceiling: the scheduler resolves these names with a single `whereIn`. Fixes [NAN-6818](https://linear.app/nango/issue/NAN-6818) ## Testing - Unit tests cover batch boundaries, merging across batches, a failing later batch, and the empty case. - Verified locally against a seeded connection with 1601 syncs: the tab now returns 200 with all 1601 rows, each carrying `schedule_status`. Probing the orchestrator directly confirms the boundary — 1000 names → 200, 1001 → 400. ## Follow-ups - The tab still fetches every sync with no pagination and re-polls every 5s — [NAN-6819](https://linear.app/nango/issue/NAN-6819). | 1 天前 | |
chore(release): 0.71.6 | 2 天前 | |
feat(auth): internal service auth (#7167) Optional Bearer auth between internal services (orchestrator and jobs). Off by default; existing deploys are unchanged until operators set secrets and flip `NANGO_INTERNAL_AUTH_REQUIRED`. ## Summary - Orchestrator and jobs HTTP APIs accept `Authorization: Bearer`, except `GET /health`. - Control plane (server, jobs, orchestrator) uses a shared static token (`NANGO_INTERNAL_AUTH_TOKEN`). - Jobs mints HMAC JWTs for runners: task-bound for `putTask`/`heartbeat`, node-bound for register/idle. The signing key stays on jobs; runners never receive `NANGO_INTERNAL_AUTH_TOKEN` or `NANGO_INTERNAL_AUTH_SIGNING_KEY`. Rollout plan [here](https://linear.app/nango/issue/NAN-6634/add-internal-auth-middleware-to-orchestrator-and-jobs#zero-downtime-rollout-2e12b4cc) --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 9 天前 | |
chore: make tsconfigs compatible with typescript-go (#6593) ## Problem Step 3 of the ESLint → oxlint migration (NAN-5769). oxlint's type-aware mode runs on the native `typescript-go` compiler (via `oxlint-tsgolint`), which has dropped several legacy tsconfig options we still use. Until they're migrated, type-aware linting errors out on the affected packages, so those files wouldn't actually be type-checked. All of these are changes we'd need for newer TypeScript regardless. ## Solution Migrate each removed option to its modern equivalent: - **root `tsconfig.json`** — drop `ignoreDeprecations: "5.0"` + `importsNotUsedAsValues: "remove"`, add `verbatimModuleSyntax: true` - **`packages/webapp` + `packages/connect-ui`** — remove `baseUrl`; the `@/*` alias still resolves via the relative `paths` entry (tsc) and the explicit Vite `alias` (build), both independent of `baseUrl` - **`scripts/one-off/*` (3 tsconfigs)** — `moduleResolution: "Node"` (node10, removed) → `"Bundler"` `verbatimModuleSyntax` surfaced one value/type export to split (`BigQueryType` in `data-ingestion`); the rest of the codebase was already compliant since `consistent-type-imports` enforces `import type`. Prereq NAN-5809 (posthog-node v5) is already on master, so `verbatimModuleSyntax` no longer trips the old posthog packaging bug. Part of NAN-5769. Sub-issue: NAN-5810. ## Testing - `npm run ts-build` passes clean (exit 0) with `verbatimModuleSyntax` enabled - `@/` alias resolution confirmed unaffected — webapp/connect-ui resolve it via an explicit Vite `alias`, not tsconfig `baseUrl` - (Follow-up) `oxlint --type-aware .` reports zero `tsconfig-error` diagnostics — verified during the migration spike | 2 个月前 | |
fix: vitest upgrade (#6315) <!-- Describe the problem and your solution --> <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> | 3 个月前 | |
feat(webhooks): add createFunction/createWebhook authoring primitive (NAN-5885) 1/n (#6447) Introduce `functions` — a trigger-agnostic primitive that separates the trigger (what initiates execution) from the handler (what runs). Webhooks are the first trigger type; `createWebhook()` is sugar for a function with a single implicit `http` trigger. Syncs and actions are unchanged. - runner-sdk: `createFunction()` / `createWebhook()` + trigger/ingress/debounce types and the `FunctionEvent` shape passed to `exec(nango, event)`. - types: `ParsedNangoFunction` + `ParsedFunctionTrigger`, additive `functions[]` on the parsed integration (kept separate from ScriptTypeLiteral while additive). - cli: babel plugin recognizes createFunction/createWebhook and injects `type: 'function'` (distinct const identifier since `function` is reserved); zero-yaml definitions parser builds ParsedNangoFunction; `nango create --webhook` scaffold + template. Backend deploy acceptance of the `function` type is intentionally out of scope for this slice and tracked as follow-up. <!-- Describe the problem and your solution --> <!-- Issue ticket number and link (if applicable) --> <!-- Testing instructions (skip if just adding/editing providers) --> | 2 个月前 | |
feat(mcp): add integrations create tool (#7002) ## Summary Add the `integrations_create` Management MCP tool. Stacked on #7001. Linear: https://linear.app/nango/issue/NAN-6295/mcp-tool-integrations-create <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/NangoHQ/nango/pull/7002?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> | 28 天前 |
借助 AI 构建产品集成
将您的产品和 AI 智能体与 900+ 个 API 相连。通过代码中的 AI 构建、运行和维护集成,依托为规模化设计的基础设施。
什么是 Nango?
Nango 是一个用于构建产品集成的开源平台。它支持 900+ 个 API,并且可与任何后端语言、AI 编码工具及智能体 SDK 协同工作。
您可以将集成逻辑编写为 TypeScript 函数,或让 AI 为您生成这些函数,然后部署到 Nango 的生产运行时环境。Nango 负责处理身份验证、执行、扩展和可观测性。
已被 Replit、Ramp、Mercor 等数百家企业投入生产使用。
工作原理
Nango 为您提供三种基础组件,可覆盖所有集成模式:
1. 身份验证(Auth)
为 900+ 个 API 提供托管式 OAuth、API 密钥和令牌刷新功能。在您的应用中嵌入白标身份验证流程。Nango 负责处理凭证、令牌存储和多租户连接管理。
// Embed auth in your frontend
nango.openConnectUI({ onEvent: (event) => { /* handle completion */ } });
2. 代理
代表用户发出经过身份验证的 API 请求。通过 Nango 的代理发送请求:它会解析服务提供商、注入凭据、处理重试和速率限制,并返回响应。
import { Nango } from '@nangohq/node';
const nango = new Nango({ secretKey: '<NANGO-SECRET-KEY>' });
// Make an authenticated request to any API
const response = await nango.get({
endpoint: '/v3/contacts',
providerConfigKey: '<INTEGRATION-ID>',
connectionId: '<CONNECTION-ID>'
});
3. 函数
将集成逻辑编写为 TypeScript 函数并部署到 Nango。函数在生产环境运行时执行,该运行时内置 API 访问、重试、存储和可观测性功能。
使用AI 构建器,根据您的用例描述生成函数。
export default async function run(nango: Nango) {
const { owner, repo, title, body } = nango.input;
const response = await nango.post({
endpoint: `/repos/${owner}/${repo}/issues`,
data: { title, body }
});
return response.data;
}
您可以构建的功能
Nango 支持所有常见的集成模式:
| 用例 | 描述 |
|---|---|
| AI 工具调用与 MCP | 赋予 AI 代理调用外部 API 的能力 |
| 数据同步 | 用于 RAG 管道、索引编制和触发器的单向或双向同步 |
| Webhook 处理 | 可靠地接收和处理来自外部 API 的 Webhook |
| API 统一 | 将 API 规范化为您自己的通用架构 |
| 操作执行 | 代表用户写入数据并执行操作 |
| 按客户配置 | 为每个客户自定义集成行为 |
快速入门
5 分钟内即可启动并运行:
1. 创建集成。 注册(免费,无需信用卡),然后在“集成”选项卡中配置新集成。
2. 授权 API。 在“连接”选项卡上,创建连接并完成身份验证流程。之后,将其嵌入您的产品中:
nango.openConnectUI({ onEvent: (event) => { /* handle completion */ } });
3. 访问 API。 检索凭证并发起经过身份验证的请求:
import { Nango } from '@nangohq/node';
const nango = new Nango({ secretKey: '<NANGO-SECRET-KEY>' });
const connection = await nango.getConnection('<INTEGRATION-ID>', '<CONNECTION-ID>');
console.log(connection.credentials);
将 Auth 流程嵌入你的产品,通过 Proxy 发起请求,或使用 Functions 构建自定义集成。
为什么选择 Nango?
AI 生成,人工可控的代码 Nango 的 AI 构建器可从自然语言生成 TypeScript 集成函数。与黑盒解决方案不同,你能获得可读的代码,可进行审查、编辑和版本控制。具备完整的类型安全和内置测试框架。
企业级基础设施 Nango 处理数十亿次 API 请求。其运行时提供租户隔离、弹性扩展、自动重试和速率限制处理。已在数百公司的生产环境中经受住考验。
开箱即支持 900+ API 的认证 为你处理 OAuth 流程、令牌刷新、凭证存储和多租户支持。无需从零构建认证,即可连接任何 API。
开源且可自托管 Nango 完全开源。可在 Nango Cloud 上运行,或在你自己的基础设施上自托管。符合 SOC 2 Type II、HIPAA 和 GDPR 标准。
适配你的工作流 可通过 CLI 和 API 完全操作。兼容任何后端语言或框架、AI 编码工具(Cursor、Codex、Claude Code)以及智能体 SDK(MCP、LangChain)。
开源版 vs. 付费版
Nango 基于 Elastic License 许可。Cloud 和企业自托管版本根据你的 计划 提供所有功能访问权限。你也可以 免费自托管,但功能会受到限制。
贡献
我们欢迎贡献 — 任何人都可以 添加对新 API 的支持。
感谢所有贡献者 ❤️