Find an Indigenous corporation by name, then read it by ICN
Find an Indigenous corporation by name, then read it by ICN
What you build: a server-side flow for a grants or procurement system. A clerk types part of a corporation’s name; your server lists the matches from the ORIC register with their ICNs; the clerk picks one; your server reads that corporation’s record by its ICN. An empty search is a real answer; an outage is not.
Before you start: a development app, then a production app
npx comms-id initmakes a development key in.env.localand prints its public key. In the Companion App, register it as a development app, enable ORIC for it, and put the app id in.env.localasCOMMS_ID_CLIENT_ID. This key reaches only the TEST service (https://api-test.comms.id): the same API, errors and authentication as LIVE, with synthetic replies.- When it works in TEST,
npx comms-id key --worker <your worker>makes the production key straight into your server’sCOMMS_ID_PRIVATE_JWKsecret and prints the public key; register it as a production app with ORIC enabled. Going live changes only the environment and the key: nothing in the code below.
A .env.local never holds a production key, and a browser never holds any key.
The code
pnpm add @comms-id/oric
find-corporation.ts:
// Find an Indigenous corporation by name, then read one record by its ICN, on your server.
import { type OricClient, outcomeOf } from "@comms-id/oric";
export interface Corporation {
readonly icn: string;
readonly name: string;
readonly status: string;
}
/** The corporations whose names contain `term`; an empty list is a real answer, an outage is not. */
export const findByName = async (term: string, oric: OricClient): Promise<readonly Corporation[]> => {
const found = await oric.search({ term });
if (found.status === "unavailable") {
throw new Error("The ORIC register did not answer; try again later.");
}
if (found.status !== "found" || !("data" in found)) {
return [];
}
return found.data.map((row) => ({ icn: row.icn, name: row.name, status: row.statusReason ?? "unknown" }));
};
/** One corporation's register record, or undefined when the ICN is not on the register. */
export const readByIcn = async (icn: string, oric: OricClient) => {
try {
const reply = await oric.lookup({ kind: "icn", value: icn });
if (reply.status === "unavailable") {
throw new Error("The ORIC register did not answer; try again later.");
}
const snapshot = reply.snapshot;
return snapshot !== undefined && snapshot.status === "found" ? snapshot.data : undefined;
} catch (error) {
if (outcomeOf(error) === "source-unavailable") {
throw new Error("The ORIC register did not answer; try again later.");
}
throw error;
}
};
search answers from the published ORIC dataset; lookup by ICN answers status: "complete" with the register record (and, when the portal answered too, its details). unavailable is a status of its own, so the function throws rather than return an empty record.
TEST first
import { createOricClient } from "@comms-id/oric/server";
import { findByName, readByIcn } from "./find-corporation";
const oric = createOricClient({
clientId: process.env.COMMS_ID_CLIENT_ID!,
privateJwk: JSON.parse(process.env.COMMS_ID_PRIVATE_JWK!),
environment: "test",
});
const matches = await findByName("Urapuntja", oric); // the published example term: one fictional match
const record = await readByIcn(matches[0]!.icn, oric); // its ICN (4172 in TEST)
await findByName("nomatch anything", oric); // []
await readByIcn("503", oric); // throws: the register did not answer
LIVE
Remove environment: "test" and use the production key. Reference: ORIC API. The attribution in each reply (Source: ... ORIC, via data.gov.au) must be shown wherever the data is.