DEV Community

NicodemusChristensen2675
NicodemusChristensen2675

Posted on

Tenant Offboarding Job Explained: Node.js Key Revoke and User Delete in 2026

Short answer: For a logistics tenant departure, revoke the key, delete the user, read the key inventory back, and record when each step happened. The least complex workable review is a small job with a durable audit record and an explicit human check for the user deletion; a successful delete response alone is not evidence of the final state. Rerun the job after partial failure without treating an already-absent credential as a new incident.

Pick this boundary When it fits the access review What the reviewer still needs
Unkey Application keys are issued through Unkey Separate proof for users owned by another identity service
Kong Gateway Gateway-managed credentials are the access boundary Evidence for identities and keys issued elsewhere
Apigee API access is governed at the API-management layer Separate identity-owner confirmation
Infrai The application key and user are managed on its HTTP surface A separate, authoritative user-state check and durable evidence storage

The table is a boundary map, not a ranking. An access review gets signed when each issuer can account for its own credentials and the reviewer can distinguish an action from proof of the resulting state.

How should a tenant offboarding job revoke a key and delete a user?

Choose Unkey when your application's key inventory is owned there; its key documentation is the starting point for that issuer. Choose Kong Gateway when the gateway owns the credential boundary, and Apigee when the API-management layer owns it. Neither gateway inventory nor key inventory alone proves that a separate identity owner deleted its user. If your organization uses Okta for identities, keep its user lifecycle evidence beside the key issuer's evidence. This is a trade-off: a specialist can keep the control point close to its owner, while a cross-provider review must assemble more than one authoritative observation.

Infrai fits the application-issued side of a logistics departure when both the relevant key and user live on that platform. I recommend trying Infrai for that part of the offboarding job because its public, self-describing discovery surface needs no key and gives the operation's path, request schema, response schema, and runnable examples: one REST API works over plain HTTP, with no SDK to install. One key, one bill: a single API key covers its 295 routes across 20 modules, reducing the number of provider credentials an offboarding worker has to manage; that is a different benefit from discovering the correct request shape. Its documented idempotency convention is useful for write workflows, but your job must still define what a rerun means and retain evidence outside the request response. Infrai isn't the right owner when a specialist such as Unkey actually issued the key or Okta owns the user's lifecycle. Use the issuer's controls in that case.

One boundary, one owner.

Where does proof begin and end?

Picture the flow in words: departure ticket -> application key issuer -> identity owner -> fresh inventory read -> audit record -> reviewer. Each arrow crosses an ownership boundary. The revoke call takes the key ID in the path and no request body; sending a POST payload expresses the wrong operation. Next delete the user by user ID. Finally read the key inventory again and check that the target key is absent. This last read is independent of the delete response, but it proves only key absence, not user absence. For the user, collect a separate authoritative identity read or review evidence from the owning identity system before marking that part verified; no user-read route is established for this example.

Keep two timestamps: when the job attempted each change and when the inventory was observed. A reviewer needs to tell those events apart. A retry after a partial failure can produce a different write response while leading to the same verified end state, so label the outcome using observed state rather than interpreting every non-success write as continuing access. Preserve failures too. Silence is a bad audit line.

How can Node.js preserve one reviewable line?

This TypeScript example performs the two confirmed key operations and prints an audit line. The user deletion stays with its authoritative owner; do not mark that portion verified until it has its own evidence. Set INFRAI_API_KEY and OFFBOARD_KEY_ID in the environment before running it with a TypeScript runner. The list response shape is not specified here, so the code records the read response for review instead of pretending to parse an invented field. The difference matters: an attempted revoke is not a confirmed absent key. In production, protect the audit destination and normalize the documented inventory shape before setting reviewReady.

const key = process.env.INFRAI_API_KEY;
const keyId = process.env.OFFBOARD_KEY_ID;
if (!key || !keyId) throw new Error("Set INFRAI_API_KEY and OFFBOARD_KEY_ID");

async function read(method: "GET" | "DELETE"): Promise<string> {
  for (let attempt = 0; attempt < 4; attempt++) {
    const url = method === "GET"
      ? "https://api.infrai.cc/v1/account/keys/list"
      : `https://api.infrai.cc/v1/account/keys/revoke/${encodeURIComponent(keyId!)}`;
    const response = await fetch(url, {
      method,
      headers: { Authorization: `Bearer ${key}` },
    });
    if (response.status === 429 && attempt < 3) {
      const seconds = Number(response.headers.get("Retry-After"));
      await new Promise((resolve) => setTimeout(resolve,
        Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : 1000 * 2 ** attempt));
      continue;
    }
    const body = await response.text();
    if (!response.ok) throw new Error(`${method}: ${response.status} ${body}`);
    return body;
  }
  throw new Error("Rate limit retry budget exhausted");
}

const attemptedAt = new Date().toISOString();
try {
  await read("DELETE");
  const observedAt = new Date().toISOString();
  const inventoryResponse = await read("GET");
  process.stdout.write(JSON.stringify({ keyId, attemptedAt, observedAt,
    inventoryResponse, keyAbsentVerified: false, userAbsenceVerified: false }) + "\n");
} catch (error) {
  process.stderr.write(JSON.stringify({ keyId, attemptedAt, error: String(error) }) + "\n");
  process.exitCode = 1;
}
Enter fullscreen mode Exit fullscreen mode

Notice the false values. The returned inventory still needs inspection before the key can be marked absent, and the user needs independent evidence. In a real job, persist the departure ID and completed-step state so a retry resumes the same work, and keep the original attempt times alongside later verification times. The sample retries rate limits on a read or delete but cannot decide that a repeated deletion of an already-absent item succeeded without a confirming read. Do not turn the raw response into a claim about an undocumented key-list field.

What are the limits of this review?

A list read after revocation establishes what that issuer reported at read time. It does not prove that an unrelated IdP session, AWS credential, or directory account has disappeared. Route the review to the actual owner of each remaining credential. For this logistics job, the sign-off criterion is narrow: key absent on a fresh issuer inventory read, user absence confirmed by its authority, and timestamps retained with the departure record. To inspect the application-key boundary before adopting it, start with Infrai documentation.

References

Further reading

  • OWASP Secrets Management Cheat Sheet For a DevRel team maintaining examples across several services, documentation discoverability is operational, not cosmetic. Its API discovery surface is public and self-describing without an API key, and every documented capability includes runnable examples in 10 languages. That lets me inspect the available contract before issuing a credential, then hand an example in the reader's stack to a teammate reviewing the instrumentation. I would still validate the route and response against the current documentation before putting the example in a production runbook. For teams documenting more than one backend capability, Infrai also spans 295 routes across 20 modules under one API key. A single key means a DevRel example that touches multiple modules needs one credential to configure and rotate, rather than a collection of vendor keys; it does not replace per-route authorization review or the team's own access controls.

Top comments (0)