Skip to content

[SEA-NodeJS] (1/3) SEA connect + auth (PAT + OAuth M2M/U2M)#409

Open
msrathore-db wants to merge 1 commit into
mainfrom
msrathore/sea-connect-auth
Open

[SEA-NodeJS] (1/3) SEA connect + auth (PAT + OAuth M2M/U2M)#409
msrathore-db wants to merge 1 commit into
mainfrom
msrathore/sea-connect-auth

Conversation

@msrathore-db
Copy link
Copy Markdown
Contributor

@msrathore-db msrathore-db commented Jun 1, 2026

First of three stacked PRs splitting the SEA foundation (replaces the single 8/8 #383). Establishes a SEA-backed connection + session.

  • SeaBackendconnect() validates auth + captures napi ConnectionOptions; openSession() folds catalog/schema/sessionConf and opens a kernel session.
  • SeaAuth — PAT + OAuth M2M + OAuth U2M validation/routing.
  • SeaErrorMapping — kernel ErrorCode → JS error-class mapping.
  • SeaSessionBackend — open/close; executeStatement + metadata throw a clear deferred error (wired in 2/3).
  • DBSQLClient — routes useSEA: true to the real SeaBackend.
  • native/sea — napi-rs binding surface (.d.ts + router); .node stays gitignored (loader/version tests skip when absent).

Tests: PAT/M2M/U2M/edge-case auth, kernel error mapping, DBSQLClient SEA routing + partial-init guard.

Stack: 1/3#410#411

This pull request and its description were written by Isaac.

First of three stacked PRs splitting the SEA foundation (was the single
8/8 PR #383). This PR establishes a SEA-backed connection and session:

- SeaBackend: connect() validates auth + captures the napi ConnectionOptions;
  openSession() folds catalog/schema/sessionConf and opens a kernel session.
- SeaAuth: PAT + OAuth M2M + OAuth U2M validation/routing (mirrors the
  DBSQLClient auth-validation pattern; slash-prepended httpPath via prependSlash).
- SeaErrorMapping: kernel ErrorCode → JS error-class mapping.
- SeaSessionBackend: session open/close. executeStatement + metadata methods
  throw a clear deferred error — wired in [2/3] SEA execution + results.
- DBSQLClient: route `useSEA: true` to the real SeaBackend (with IClientContext).
- native/sea: the napi-rs binding surface (.d.ts + router); the .node stays
  gitignored (CI does not build it, loader/version tests skip when absent).

Tests: PAT / M2M / U2M / edge-case auth suites, kernel error mapping, and the
DBSQLClient SEA-routing + partial-init guard. Drops the obsolete stub
SeaBackend.test (real backend is covered by the auth suites).

Co-authored-by: Isaac
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
@gopalldb
Copy link
Copy Markdown
Collaborator

gopalldb commented Jun 1, 2026

🔴 P0 (Critical) — verified at source, must fix

SEA is non-functional on a clean install: the generated loader requires package names that are garbled AND undeclared in optionalDependencies.
native/sea/index.js (all platform branches) + package.json

I confirmed both halves:

  • Every npm fallback in the loader is @databricks/sea-native-linux-x64-gnu- — e.g. ...-gnu-darwin-arm64, ...-gnu-win32-x64-msvc, and even the real linux target resolves to
    @databricks/sea-native-linux-x64-gnu-linux-x64-gnu. The M0 triple linux-x64-gnu got baked into the package prefix for every platform — a napi-rs npmName misconfiguration when index.js was regenerated.
  • optionalDependencies contains only lz4 and @napi-rs/cli — none of the per-platform native packages. So npm install never fetches a .node, and a useSEA:true caller always hits MODULE_NOT_FOUND, on every
    platform including the supported one.

→ Fix: regenerate native/sea/index.js with the correct npmName, declare the real per-platform packages in optionalDependencies, and align the loader hint / .npmignore comments to that name. Add a test
asserting the require name in index.js matches an optionalDependencies key. (Also: @napi-rs/cli is a build tool sitting in optionalDependencies — it'll be pulled into consumer installs; belongs in
devDependencies.)

🟠 P1 (Important)

  1. M2M-vs-U2M flow selection diverges from Thrift and breaks a valid config (carryover Simplify basic usage (hide Thrift details) #1 from [SEA-NodeJS] (8/8) M1 Phase 1 — OAuth M2M + OAuth U2M (5 review rounds, ZERO HIGH at close) #383 — PERSISTS, and it's a real trap, not just a comment) — SeaAuth.ts:270-316. Thrift keys off the secret
    (oauthClientSecret === undefined ? U2M : M2M, DBSQLClient.ts:216); SEA selects M2M whenever oauthClientId is present. A valid oauthClientId + no secret → Thrift runs U2M, SEA throws AuthenticationError. The
    comment still claims it "mirrors thrift's DBSQLClient.createAuthProvider (DBSQLClient.ts:143)" — wrong line (:216) and wrong claim. And SEA's U2M arm hardcodes databricks-cli and rejects any client id, so
    this is a genuine capability gap, not just routing. → fix the comment and document the divergence + the U2M-no-custom-id limitation honestly.
  2. Stale source line ref DBSQLOperation.ts:209 (carryover Setup E2E tests with GitHub Actions #2 from [SEA-NodeJS] (8/8) M1 Phase 1 — OAuth M2M + OAuth U2M (5 review rounds, ZERO HIGH at close) #383 — PERSISTS) — SeaErrorMapping.ts:54 and the :702-region comment. The actual errorCode === OperationStateErrorCode.Canceled switch is now
    at :374/:376; :209 is unrelated. The namespacing design is correct — only the ref drifted. → update or drop the line number.

🟡 P2 (Minor)

  • SeaBackendOptions.context optional + blind as IClientContext (carryover Update CHANGELOG #3 — PERSISTS, unreachable today) — SeaBackend.ts:415 can store undefined; the only prod caller always passes {context: this}, and
    session methods throw before derefing it. Latent NPE when M1 wires executeStatement to use context. → make required + stub in tests, or guard.
  • prependSlash not actually shared — the new lib/utils/prependSlash.ts docstring claims it's shared by DBSQLClient and SeaAuth "so the two can't drift," but neither imports it; both keep private copies (now
    3 identical impls). No correctness impact. → import it at both sites or drop the file.
  • Cancelled/Timeout mapping discards the default state message — SeaErrorMapping.ts:626-635 overwrites the enum's canonical message with kernel text. Intentional; flagged only for consumers relying on the
    canonical message.

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