Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
"scripts": {
"demo": "tsx scripts/demo.ts",
"dev": "pnpm --parallel --filter @keyring/server --filter @keyring/web dev",
"build": "pnpm -r run build",
"build": "tsc -b --pretty false && pnpm --filter @keyring/web run build",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"typecheck": "pnpm -r run typecheck",
"typecheck": "tsc -b --pretty false && pnpm --filter @keyring/web exec tsc -p tsconfig.json --noEmit",
"format": "prettier --write .",
"format:check": "prettier --check .",
"db:migrate": "pnpm --filter @keyring/server db:migrate",
Expand Down
4 changes: 2 additions & 2 deletions packages/connectors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"types": "./dist/index.d.ts",
"files": ["dist", "fixtures"],
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit"
"build": "tsc -b tsconfig.json --pretty false",
"typecheck": "tsc -b tsconfig.json --pretty false"
},
"dependencies": {
"@keyring/core": "workspace:*"
Expand Down
6 changes: 4 additions & 2 deletions packages/connectors/src/github/connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,14 @@ export function createGitHubConnector(options: GitHubConnectorOptions): Connecto
return { ok: false, error: "not a github grant" };
}

const login = grant.principal.identifiers.find((i) => i.kind === "username")?.value;
const login = grant.principal.identifiers.find(
(i: Identifier) => i.kind === "username",
)?.value;
const resourceId = String(grant.resource.id);
const teamMatch = resourceId.match(/^([^/]+)\/team:(.+)$/);
const patMatch = resourceId.match(/^([^/]+)\/pat:(.+)$/);
const deployKeyId = grant.principal.identifiers.find(
(i) => i.kind === "key_id" && i.source === "github_deploy_keys",
(i: Identifier) => i.kind === "key_id" && i.source === "github_deploy_keys",
)?.value;

// --- Team membership ---
Expand Down
5 changes: 3 additions & 2 deletions packages/connectors/src/google-workspace/connector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createGrant, type Grant } from "@keyring/core";
import { createGrant, type Grant, type Identifier } from "@keyring/core";

import { asArray, asObject, callJson, paginateTokens } from "../mcp/paginate.js";
import { McpToolError, type McpToolCaller } from "../mcp/types.js";
Expand Down Expand Up @@ -374,7 +374,8 @@ export function createGoogleWorkspaceConnector(
return { ok: false, error: "not a google_workspace grant" };
}
const email = grant.principal.identifiers.find(
(i) => i.kind === "work_email" || i.kind === "personal_email",
(i: Identifier) =>
i.kind === "work_email" || i.kind === "personal_email",
)?.value;
if (!email) return { ok: false, error: "missing email identifier" };

Expand Down
4 changes: 3 additions & 1 deletion packages/connectors/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts"]
"exclude": ["src/**/*.test.ts"],
"references": [{ "path": "../core" }]
}
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"types": "./dist/index.d.ts",
"files": ["dist"],
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"build": "tsc -b tsconfig.json --pretty false",
"typecheck": "tsc -b tsconfig.json --pretty false",
"reconcile": "node dist/identity/cli.js"
},
"bin": {
Expand Down
1 change: 1 addition & 0 deletions packages/core/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
],
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"build": "tsc -b tsconfig.json --pretty false",
"typecheck": "tsc -b tsconfig.json --pretty false",
"start": "node dist/index.js",
"db:generate": "drizzle-kit generate",
"db:migrate": "tsx src/db/migrate-cli.ts"
Expand Down
56 changes: 55 additions & 1 deletion packages/server/src/db/audit-append-only.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
appendAuditRecord,
asApprovalCardId,
} from "@keyring/core";
import { sql } from "drizzle-orm";
import { inArray, sql } from "drizzle-orm";
import { afterAll, beforeAll, describe, expect, it } from "vitest";

import type { AppDb } from "./client.js";
Expand Down Expand Up @@ -110,4 +110,58 @@ describe("audit_records append-only", () => {
expect(after.ok).toBe(true);
expect(after.count).toBe(before.count + 10);
});

it("restores the timestamp default after concurrent identical-time appends", async () => {
const recordedAt = "2026-08-29T23:00:00.000Z";

try {
await db.execute(
sql`ALTER TABLE audit_records ALTER COLUMN recorded_at SET DEFAULT '2026-08-29T23:00:00.000Z'::timestamptz`,
);

const appended = await Promise.all(
Array.from({ length: 20 }, (_, i) =>
appendChainedAudit(db, {
cardId: asApprovalCardId(
`card-identical-recorded-at-${i}-${crypto.randomUUID()}`,
),
action: "approve",
approvedBy: "judge@acme.com",
approvedAt: new Date(recordedAt),
executedAt: new Date(recordedAt),
result: "success",
evidenceSnapshot: evidence,
}),
),
);

const appendedRows = await db
.select({
id: auditRecords.id,
recordedAt: auditRecords.recordedAt,
})
.from(auditRecords)
.where(
inArray(
auditRecords.id,
appended.map((record) => record.id),
),
);
expect(appendedRows).toHaveLength(20);
expect(
new Set(appendedRows.map((row) => row.recordedAt.toISOString())),
).toEqual(new Set([recordedAt]));

const allRows = await db
.select({ prevHash: auditRecords.prevHash })
.from(auditRecords);
const prevHashes = allRows.map((row) => row.prevHash);
expect(new Set(prevHashes).size).toBe(prevHashes.length);
expect((await verifyStoredAuditChain(db)).ok).toBe(true);
} finally {
await db.execute(
sql`ALTER TABLE audit_records ALTER COLUMN recorded_at SET DEFAULT now()`,
);
}
});
});
4 changes: 3 additions & 1 deletion packages/server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts"]
"exclude": ["src/**/*.test.ts"],
"references": [{ "path": "../core" }, { "path": "../connectors" }]
}
8 changes: 8 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"files": [],
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/connectors" },
{ "path": "./packages/server" }
]
}
Loading