From 74716a7ff891691fd9a105d2eb4272a4bae48c24 Mon Sep 17 00:00:00 2001 From: yanny-sec Date: Wed, 22 Jul 2026 15:26:36 +0100 Subject: [PATCH] chore(license): add licence-header pre-commit hook and apply Apache-2.0 SPDX headers repo-wide --- .pre-commit-config.yaml | 12 ++- CONTRIBUTING.md | 12 ++- backend/proto/event.proto | 3 + examples/python/create_agent.py | 3 + examples/python/hitl_credential_leak.py | 3 + examples/python/manual_instrumentation.py | 3 + examples/python/quickstart.py | 3 + examples/python/react_agent.py | 3 + examples/typescript/hitl_credential_leak.ts | 3 + .../(dashboard)/agents/[agent_id]/page.tsx | 3 + frontend/app/(dashboard)/agents/page.tsx | 3 + frontend/app/(dashboard)/events/page.tsx | 3 + frontend/app/(dashboard)/layout.tsx | 3 + frontend/app/(dashboard)/mcp/page.tsx | 3 + frontend/app/(dashboard)/page.tsx | 3 + frontend/app/(dashboard)/reviews/page.tsx | 3 + .../sessions/[session_id]/page.tsx | 3 + frontend/app/(dashboard)/settings/page.tsx | 3 + frontend/app/change-password/page.tsx | 3 + frontend/app/layout.tsx | 3 + frontend/app/login/page.tsx | 3 + frontend/components/alert-explanation.tsx | 3 + frontend/components/badge.tsx | 3 + frontend/components/icons/brands/clickup.tsx | 3 + frontend/components/icons/brands/discord.tsx | 3 + frontend/components/icons/brands/telegram.tsx | 3 + frontend/components/json-block.tsx | 3 + frontend/components/pagination.tsx | 3 + frontend/components/sidebar.tsx | 3 + frontend/components/theme-provider.tsx | 3 + frontend/components/theme-toggle.tsx | 3 + frontend/components/time-range.tsx | 3 + frontend/components/topbar.tsx | 3 + frontend/components/ui/dialog.tsx | 3 + frontend/lib/agent-profile-templates.ts | 3 + frontend/lib/utils.ts | 3 + frontend/next.config.js | 3 + frontend/package.json | 1 + frontend/postcss.config.js | 3 + frontend/tailwind.config.ts | 3 + .../claude-code/adrian_cc/__init__.py | 3 + integrations/claude-code/adrian_cc/agent.py | 3 + .../claude-code/adrian_cc/proto/__init__.py | 2 + .../adrian_cc/proto/buf/__init__.py | 3 + .../adrian_cc/proto/buf/validate/__init__.py | 3 + integrations/claude-code/adrian_cc/tracker.py | 3 + .../claude-code/adrian_cc/transcript.py | 3 + integrations/claude-code/bin/adrian-python | 2 + integrations/claude-code/tests/__init__.py | 2 + integrations/claude-code/tests/test_agent.py | 3 + .../claude-code/tests/test_integration.py | 3 + .../claude-code/tests/test_multi_agent.py | 3 + .../tests/test_state_and_subagent.py | 3 + .../claude-code/tests/test_transcript.py | 3 + integrations/claude-code/tools/regen-proto.sh | 3 + proto/event.proto | 3 + scripts/add_license_header.py | 75 +++++++++++++++++++ scripts/setup.py | 3 + sdk/python/adrian/__init__.py | 3 + sdk/python/adrian/adapters/__init__.py | 3 + sdk/python/adrian/adapters/langgraph.py | 3 + sdk/python/adrian/callbacks.py | 3 + sdk/python/adrian/config.py | 3 + sdk/python/adrian/context.py | 3 + sdk/python/adrian/format/__init__.py | 3 + sdk/python/adrian/format/types.py | 3 + sdk/python/adrian/handler.py | 3 + sdk/python/adrian/handlers/__init__.py | 3 + sdk/python/adrian/handlers/jsonl.py | 3 + sdk/python/adrian/hooks.py | 3 + sdk/python/adrian/identity.py | 3 + sdk/python/adrian/mcp.py | 3 + sdk/python/adrian/pairing.py | 3 + sdk/python/adrian/pii/__init__.py | 3 + sdk/python/adrian/pii/_engine.py | 3 + sdk/python/adrian/pii/_patterns.py | 3 + sdk/python/adrian/pii/_redactor.py | 3 + sdk/python/adrian/pii/_strategies.py | 3 + sdk/python/adrian/proto/__init__.py | 3 + sdk/python/adrian/proto/buf/__init__.py | 3 + .../adrian/proto/buf/validate/__init__.py | 3 + sdk/python/adrian/session_persistence.py | 3 + sdk/python/adrian/types.py | 3 + sdk/python/adrian/ws.py | 3 + sdk/python/tests/__init__.py | 3 + sdk/python/tests/test_block_mode.py | 3 + sdk/python/tests/test_block_mode_races.py | 3 + sdk/python/tests/test_exec_modes.py | 3 + sdk/python/tests/test_handler.py | 3 + sdk/python/tests/test_init.py | 3 + sdk/python/tests/test_mcp.py | 3 + .../tests/test_parent_context_scenarios.py | 3 + sdk/python/tests/test_pii_engine.py | 3 + sdk/python/tests/test_pii_integration.py | 3 + sdk/python/tests/test_pii_patterns.py | 3 + sdk/python/tests/test_pii_redactor.py | 3 + sdk/python/tests/test_resilience.py | 3 + sdk/python/tests/test_session_persistence.py | 3 + sdk/python/tests/test_ws.py | 3 + sdk/python/tools/regen-proto.sh | 3 + sdk/typescript/package.json | 1 + .../packages/core/src/capture/common.ts | 3 + .../packages/core/src/capture/index.ts | 3 + sdk/typescript/packages/core/src/config.ts | 3 + sdk/typescript/packages/core/src/context.ts | 3 + .../packages/core/src/format/types.ts | 3 + sdk/typescript/packages/core/src/handler.ts | 3 + .../packages/core/src/handlers/jsonl.ts | 3 + sdk/typescript/packages/core/src/hooks.ts | 3 + sdk/typescript/packages/core/src/identity.ts | 3 + sdk/typescript/packages/core/src/index.ts | 3 + sdk/typescript/packages/core/src/mcp.ts | 3 + sdk/typescript/packages/core/src/pairing.ts | 3 + .../packages/core/src/pii/engine.ts | 3 + sdk/typescript/packages/core/src/pii/index.ts | 3 + .../packages/core/src/pii/patterns.ts | 3 + .../packages/core/src/pii/redactor.ts | 3 + .../packages/core/src/pii/strategies.ts | 3 + sdk/typescript/packages/core/src/policy.ts | 3 + .../packages/core/src/proto/schema.ts | 3 + sdk/typescript/packages/core/src/registry.ts | 3 + .../packages/core/src/sessionPersistence.ts | 3 + sdk/typescript/packages/core/src/types.ts | 3 + sdk/typescript/packages/core/src/ws.ts | 3 + .../packages/core/tests/capture.test.ts | 3 + .../packages/core/tests/init.test.ts | 3 + .../packages/core/tests/jsonl.test.ts | 3 + .../packages/core/tests/pairing.test.ts | 3 + .../packages/core/tests/pii.test.ts | 3 + .../packages/core/tests/policy.test.ts | 3 + .../packages/core/tests/proto.test.ts | 3 + .../packages/core/tests/session.test.ts | 3 + sdk/typescript/packages/core/tests/ws.test.ts | 3 + sdk/typescript/packages/core/tsup.config.ts | 3 + sdk/typescript/packages/openai/src/index.ts | 3 + .../packages/openai/tests/openai.test.ts | 3 + 136 files changed, 486 insertions(+), 5 deletions(-) create mode 100644 scripts/add_license_header.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e476135..aedf7a3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,8 @@ # Adrian pre-commit hooks. Run on every `git commit` once `pre-commit # install` has been run from this repo's root (see CONTRIBUTING.md). -# Scoped to Python files under `sdk/python/` and `scripts/`. +# Formatting/lint hooks are scoped to Python files under `sdk/python/` +# and `scripts/`; the licence-header hook covers Go, Python, TypeScript, +# JavaScript, proto and shell sources repo-wide. default_install_hook_types: [pre-commit] default_language_version: @@ -34,6 +36,14 @@ repos: - repo: local hooks: + - id: license-header + name: licence header + entry: python3 scripts/add_license_header.py + language: system + files: \.(go|py|pyi|ts|tsx|js|mjs|cjs|proto|sh)$ + # Vendored code keeps its own licence; generated proto bindings + # would lose the header on regeneration. + exclude: (^|/)vendor/|(^|/)node_modules/|\.pb\.go$|_pb2(_grpc)?\.pyi?$ - id: basedpyright name: basedpyright entry: basedpyright diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a7789e..7e3d70f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,9 +42,12 @@ See [`sdk/typescript/README.md`](sdk/typescript/README.md) for usage examples. After `pre-commit install`, every `git commit` runs the configured hooks on staged files: `ruff format`, `ruff check --fix`, `basedpyright` on -`sdk/python/adrian/`, plus the standard whitespace / YAML / TOML checks. Hooks that -modify files (formatter, autofix) leave the commit aborted; re-stage the files -and commit again. +`sdk/python/adrian/`, plus the standard whitespace / YAML / TOML checks. A +licence-header hook prepends the Apache-2.0 SPDX header to any staged Go, +Python, TypeScript, JavaScript, proto or shell file that lacks one (vendored +code and generated proto bindings excluded). Hooks that +modify files (formatter, autofix, header) leave the commit aborted; re-stage +the files and commit again. To run the hooks across the whole tree on demand without committing: @@ -53,7 +56,8 @@ pre-commit run --all-files ``` The config lives at [`.pre-commit-config.yaml`](.pre-commit-config.yaml). -Only Python files under `sdk/python/` and `scripts/` are in scope. +Formatting and lint hooks cover Python under `sdk/python/` and `scripts/`; +the licence-header hook covers source files repo-wide. ## Style diff --git a/backend/proto/event.proto b/backend/proto/event.proto index ca9026b..daf7e59 100644 --- a/backend/proto/event.proto +++ b/backend/proto/event.proto @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + syntax = "proto3"; package adrian.core_api.v1; diff --git a/examples/python/create_agent.py b/examples/python/create_agent.py index 292c1b5..7bddf2e 100644 --- a/examples/python/create_agent.py +++ b/examples/python/create_agent.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 SecureAgentics + """Adrian with a LangChain agent (``create_agent``). The current LangChain agent constructor diff --git a/examples/python/hitl_credential_leak.py b/examples/python/hitl_credential_leak.py index c3e97ab..3db78c9 100644 --- a/examples/python/hitl_credential_leak.py +++ b/examples/python/hitl_credential_leak.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 SecureAgentics + """Adrian Human Review example: human-in-the-loop tool gating. Builds a small LangGraph agent (gpt-4o-mini + a ``send_email`` tool) diff --git a/examples/python/manual_instrumentation.py b/examples/python/manual_instrumentation.py index b31b7cb..50b90fc 100644 --- a/examples/python/manual_instrumentation.py +++ b/examples/python/manual_instrumentation.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 SecureAgentics + """Adrian with manual instrumentation (``auto_instrument=False``). Mirrors :mod:`quickstart` but opts out of the SDK's import-time diff --git a/examples/python/quickstart.py b/examples/python/quickstart.py index 00a3925..b02e634 100644 --- a/examples/python/quickstart.py +++ b/examples/python/quickstart.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 SecureAgentics + """Adrian quickstart: a single async LLM call captured by the SDK. The simplest possible agent code Adrian can monitor: a bare diff --git a/examples/python/react_agent.py b/examples/python/react_agent.py index 9b9d1e1..ac8e506 100644 --- a/examples/python/react_agent.py +++ b/examples/python/react_agent.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2026 SecureAgentics + """Adrian with a LangGraph ReAct agent (``create_react_agent``). ``langgraph.prebuilt.create_react_agent`` is the long-standing prebuilt diff --git a/examples/typescript/hitl_credential_leak.ts b/examples/typescript/hitl_credential_leak.ts index bf4438b..2f12039 100644 --- a/examples/typescript/hitl_credential_leak.ts +++ b/examples/typescript/hitl_credential_leak.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + /** * Adrian Human Review example (TypeScript): human-in-the-loop tool gating. * diff --git a/frontend/app/(dashboard)/agents/[agent_id]/page.tsx b/frontend/app/(dashboard)/agents/[agent_id]/page.tsx index 808e187..c661510 100644 --- a/frontend/app/(dashboard)/agents/[agent_id]/page.tsx +++ b/frontend/app/(dashboard)/agents/[agent_id]/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/(dashboard)/agents/page.tsx b/frontend/app/(dashboard)/agents/page.tsx index 9374ba4..86eba12 100644 --- a/frontend/app/(dashboard)/agents/page.tsx +++ b/frontend/app/(dashboard)/agents/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/(dashboard)/events/page.tsx b/frontend/app/(dashboard)/events/page.tsx index 236201c..9d3d133 100644 --- a/frontend/app/(dashboard)/events/page.tsx +++ b/frontend/app/(dashboard)/events/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useMemo, useState } from 'react' diff --git a/frontend/app/(dashboard)/layout.tsx b/frontend/app/(dashboard)/layout.tsx index 2711c88..f8c8fe4 100644 --- a/frontend/app/(dashboard)/layout.tsx +++ b/frontend/app/(dashboard)/layout.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useState } from 'react' diff --git a/frontend/app/(dashboard)/mcp/page.tsx b/frontend/app/(dashboard)/mcp/page.tsx index 7736ca1..1c52368 100644 --- a/frontend/app/(dashboard)/mcp/page.tsx +++ b/frontend/app/(dashboard)/mcp/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/(dashboard)/page.tsx b/frontend/app/(dashboard)/page.tsx index 1b2978f..d680c95 100644 --- a/frontend/app/(dashboard)/page.tsx +++ b/frontend/app/(dashboard)/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useMemo, useState } from 'react' diff --git a/frontend/app/(dashboard)/reviews/page.tsx b/frontend/app/(dashboard)/reviews/page.tsx index 0d3f65c..4111e16 100644 --- a/frontend/app/(dashboard)/reviews/page.tsx +++ b/frontend/app/(dashboard)/reviews/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/(dashboard)/sessions/[session_id]/page.tsx b/frontend/app/(dashboard)/sessions/[session_id]/page.tsx index 806f519..9facda5 100644 --- a/frontend/app/(dashboard)/sessions/[session_id]/page.tsx +++ b/frontend/app/(dashboard)/sessions/[session_id]/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/(dashboard)/settings/page.tsx b/frontend/app/(dashboard)/settings/page.tsx index bf0aa95..0b8ec34 100644 --- a/frontend/app/(dashboard)/settings/page.tsx +++ b/frontend/app/(dashboard)/settings/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useEffect, useState } from 'react' diff --git a/frontend/app/change-password/page.tsx b/frontend/app/change-password/page.tsx index 4fafcb3..eaf54ad 100644 --- a/frontend/app/change-password/page.tsx +++ b/frontend/app/change-password/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useState } from 'react' diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 6ba83cd..81bdcd3 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + import type { Metadata } from 'next' import './globals.css' import { ThemeProvider, themeInitScript } from '@/components/theme-provider' diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx index cb59a54..b8aebb3 100644 --- a/frontend/app/login/page.tsx +++ b/frontend/app/login/page.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { useState } from 'react' diff --git a/frontend/components/alert-explanation.tsx b/frontend/components/alert-explanation.tsx index ac51c52..9765afd 100644 --- a/frontend/components/alert-explanation.tsx +++ b/frontend/components/alert-explanation.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + 'use client' import { resolveAlert, useMadAlerts, type MadAlert } from '@/lib/mad-alerts' diff --git a/frontend/components/badge.tsx b/frontend/components/badge.tsx index 04c6975..9dd476f 100644 --- a/frontend/components/badge.tsx +++ b/frontend/components/badge.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + export function Badge({ label, className }: { label: string; className: string }) { return ( diff --git a/frontend/components/icons/brands/clickup.tsx b/frontend/components/icons/brands/clickup.tsx index 73167a2..b7a2e36 100644 --- a/frontend/components/icons/brands/clickup.tsx +++ b/frontend/components/icons/brands/clickup.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + // ClickUp uses a three-color gradient mark. Inline SVG keeps the gradient // IDs scoped via a stable unique suffix to avoid clashes when the icon is // rendered multiple times on the same page. diff --git a/frontend/components/icons/brands/discord.tsx b/frontend/components/icons/brands/discord.tsx index 8f9f09b..ff78cec 100644 --- a/frontend/components/icons/brands/discord.tsx +++ b/frontend/components/icons/brands/discord.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + export function DiscordIcon({ size = 28 }: { size?: number }) { return ( diff --git a/frontend/components/icons/brands/telegram.tsx b/frontend/components/icons/brands/telegram.tsx index d9529f0..c2e188b 100644 --- a/frontend/components/icons/brands/telegram.tsx +++ b/frontend/components/icons/brands/telegram.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + export function TelegramIcon({ size = 28 }: { size?: number }) { return ( diff --git a/frontend/components/json-block.tsx b/frontend/components/json-block.tsx index f7d3474..7881ef4 100644 --- a/frontend/components/json-block.tsx +++ b/frontend/components/json-block.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2026 SecureAgentics + // JsonBlock renders a value as a pretty-printed, syntax-highlighted //
. Tokenises the JSON.stringify output with a single regex
 // pass and wraps each token in a span with a Tailwind colour class:
diff --git a/frontend/components/pagination.tsx b/frontend/components/pagination.tsx
index 312e814..7421cca 100644
--- a/frontend/components/pagination.tsx
+++ b/frontend/components/pagination.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 export function Pagination({
diff --git a/frontend/components/sidebar.tsx b/frontend/components/sidebar.tsx
index 1e01d5f..45b04d8 100644
--- a/frontend/components/sidebar.tsx
+++ b/frontend/components/sidebar.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 import { useEffect, useState } from 'react'
diff --git a/frontend/components/theme-provider.tsx b/frontend/components/theme-provider.tsx
index c1d7687..cfdfd8e 100644
--- a/frontend/components/theme-provider.tsx
+++ b/frontend/components/theme-provider.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 // Minimal theme provider — no deps. Persists choice to localStorage and
diff --git a/frontend/components/theme-toggle.tsx b/frontend/components/theme-toggle.tsx
index 5352766..e8d6d35 100644
--- a/frontend/components/theme-toggle.tsx
+++ b/frontend/components/theme-toggle.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 // Three-way segmented toggle: light / system / dark.
diff --git a/frontend/components/time-range.tsx b/frontend/components/time-range.tsx
index 8a2c7c6..3193f6b 100644
--- a/frontend/components/time-range.tsx
+++ b/frontend/components/time-range.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 export type TimeRange = '1h' | '24h' | '7d' | '30d' | 'custom'
diff --git a/frontend/components/topbar.tsx b/frontend/components/topbar.tsx
index b156383..73e509a 100644
--- a/frontend/components/topbar.tsx
+++ b/frontend/components/topbar.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 import { useRouter } from 'next/navigation'
diff --git a/frontend/components/ui/dialog.tsx b/frontend/components/ui/dialog.tsx
index 441402a..d42e055 100644
--- a/frontend/components/ui/dialog.tsx
+++ b/frontend/components/ui/dialog.tsx
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 'use client'
 
 // Minimal accessible-ish modal primitive. We intentionally skip Radix - the
diff --git a/frontend/lib/agent-profile-templates.ts b/frontend/lib/agent-profile-templates.ts
index 45edeaf..b13d57e 100644
--- a/frontend/lib/agent-profile-templates.ts
+++ b/frontend/lib/agent-profile-templates.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 /**
  * Starter templates for the Agent Profile editor.
  *
diff --git a/frontend/lib/utils.ts b/frontend/lib/utils.ts
index b538032..ef3bb26 100644
--- a/frontend/lib/utils.ts
+++ b/frontend/lib/utils.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 export function timeAgo(date: string | Date): string {
   const seconds = Math.floor((Date.now() - new Date(date).getTime()) / 1000)
   if (seconds < 60) return `${seconds}s ago`
diff --git a/frontend/next.config.js b/frontend/next.config.js
index 1bb13ec..6e4bab5 100644
--- a/frontend/next.config.js
+++ b/frontend/next.config.js
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 /** @type {import('next').NextConfig} */
 const nextConfig = {
   output: 'standalone',
diff --git a/frontend/package.json b/frontend/package.json
index f4867d1..de14ab1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -2,6 +2,7 @@
   "name": "adrian-dashboard",
   "version": "1.0.0",
   "private": true,
+  "license": "Apache-2.0",
   "scripts": {
     "dev": "next dev --port 3000",
     "build": "next build",
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
index 33ad091..2cc84f0 100644
--- a/frontend/postcss.config.js
+++ b/frontend/postcss.config.js
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 module.exports = {
   plugins: {
     tailwindcss: {},
diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts
index 1a68a91..3412767 100644
--- a/frontend/tailwind.config.ts
+++ b/frontend/tailwind.config.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { Config } from 'tailwindcss'
 
 const config: Config = {
diff --git a/integrations/claude-code/adrian_cc/__init__.py b/integrations/claude-code/adrian_cc/__init__.py
index 2c5bd21..72d43cf 100644
--- a/integrations/claude-code/adrian_cc/__init__.py
+++ b/integrations/claude-code/adrian_cc/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian for Claude Code - runtime security monitoring via hooks.
 
 Intercepts Claude Code tool calls through the native hooks system,
diff --git a/integrations/claude-code/adrian_cc/agent.py b/integrations/claude-code/adrian_cc/agent.py
index 2db860c..fcd6418 100644
--- a/integrations/claude-code/adrian_cc/agent.py
+++ b/integrations/claude-code/adrian_cc/agent.py
@@ -1,4 +1,7 @@
 #!/usr/bin/env python3
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian CC Plugin - Claude Code hook handler.
 
 Each hook invocation:
diff --git a/integrations/claude-code/adrian_cc/proto/__init__.py b/integrations/claude-code/adrian_cc/proto/__init__.py
index e69de29..43660d7 100644
--- a/integrations/claude-code/adrian_cc/proto/__init__.py
+++ b/integrations/claude-code/adrian_cc/proto/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
diff --git a/integrations/claude-code/adrian_cc/proto/buf/__init__.py b/integrations/claude-code/adrian_cc/proto/buf/__init__.py
index 5838411..7a1f6b4 100644
--- a/integrations/claude-code/adrian_cc/proto/buf/__init__.py
+++ b/integrations/claude-code/adrian_cc/proto/buf/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Vendored buf.validate protobuf stubs."""
diff --git a/integrations/claude-code/adrian_cc/proto/buf/validate/__init__.py b/integrations/claude-code/adrian_cc/proto/buf/validate/__init__.py
index 265ad6d..f05860b 100644
--- a/integrations/claude-code/adrian_cc/proto/buf/validate/__init__.py
+++ b/integrations/claude-code/adrian_cc/proto/buf/validate/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Vendored buf.validate protobuf validation stubs."""
diff --git a/integrations/claude-code/adrian_cc/tracker.py b/integrations/claude-code/adrian_cc/tracker.py
index f64e44b..82bb0b1 100644
--- a/integrations/claude-code/adrian_cc/tracker.py
+++ b/integrations/claude-code/adrian_cc/tracker.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Stateful tracker for Claude Code sessions.
 
 Maintains three pieces of state across hook calls within a daemon:
diff --git a/integrations/claude-code/adrian_cc/transcript.py b/integrations/claude-code/adrian_cc/transcript.py
index 96bb8ba..23083c5 100644
--- a/integrations/claude-code/adrian_cc/transcript.py
+++ b/integrations/claude-code/adrian_cc/transcript.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Transcript parser - extracts reasoning, user prompts, and invocation context.
 
 Claude Code's transcript is a JSONL file where each line is a
diff --git a/integrations/claude-code/bin/adrian-python b/integrations/claude-code/bin/adrian-python
index f1d240d..02f03fb 100755
--- a/integrations/claude-code/bin/adrian-python
+++ b/integrations/claude-code/bin/adrian-python
@@ -1,4 +1,6 @@
 #!/usr/bin/env sh
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
 # Cross-platform launcher for the Adrian Claude Code plugin.
 # Linux/macOS run this directly. On Windows, Claude Code's default hook shell
 # is Git Bash, which runs this too (the adrian-python.cmd sibling covers
diff --git a/integrations/claude-code/tests/__init__.py b/integrations/claude-code/tests/__init__.py
index e69de29..43660d7 100644
--- a/integrations/claude-code/tests/__init__.py
+++ b/integrations/claude-code/tests/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
diff --git a/integrations/claude-code/tests/test_agent.py b/integrations/claude-code/tests/test_agent.py
index d32599f..43cd047 100644
--- a/integrations/claude-code/tests/test_agent.py
+++ b/integrations/claude-code/tests/test_agent.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 # pyright: reportPrivateUsage=false
 """Tests for the hook agent - event building, verdict handling, mode logic."""
 
diff --git a/integrations/claude-code/tests/test_integration.py b/integrations/claude-code/tests/test_integration.py
index fa9b813..115ca9a 100644
--- a/integrations/claude-code/tests/test_integration.py
+++ b/integrations/claude-code/tests/test_integration.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Integration tests - full hook flow against the live Adrian backend.
 
 These tests require the Adrian backend running on localhost:8080 with
diff --git a/integrations/claude-code/tests/test_multi_agent.py b/integrations/claude-code/tests/test_multi_agent.py
index eccc935..65fa131 100644
--- a/integrations/claude-code/tests/test_multi_agent.py
+++ b/integrations/claude-code/tests/test_multi_agent.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Multi-agent integration tests - nested sub-agents, parallel agents, full DB verification.
 
 Tests the complete flow: Claude Code → Plugin → Adrian Backend with
diff --git a/integrations/claude-code/tests/test_state_and_subagent.py b/integrations/claude-code/tests/test_state_and_subagent.py
index 4b7e4c5..b768218 100644
--- a/integrations/claude-code/tests/test_state_and_subagent.py
+++ b/integrations/claude-code/tests/test_state_and_subagent.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 # pyright: reportPrivateUsage=false
 """Tests for the state locking/atomic-write machinery, the sub-agent hierarchy
 stack helpers, and the deterministic transcript-by-agent_id prompt recovery."""
diff --git a/integrations/claude-code/tests/test_transcript.py b/integrations/claude-code/tests/test_transcript.py
index 9316c5b..4e41d7b 100644
--- a/integrations/claude-code/tests/test_transcript.py
+++ b/integrations/claude-code/tests/test_transcript.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 # pyright: reportPrivateUsage=false
 """Tests for transcript parser."""
 
diff --git a/integrations/claude-code/tools/regen-proto.sh b/integrations/claude-code/tools/regen-proto.sh
index 6aeb907..fdc2e28 100755
--- a/integrations/claude-code/tools/regen-proto.sh
+++ b/integrations/claude-code/tools/regen-proto.sh
@@ -1,4 +1,7 @@
 #!/usr/bin/env bash
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 # Regenerate adrian_cc/proto/event_pb2.py + event_pb2.pyi from the repo-root
 # canonical proto (//proto/event.proto) so the plugin's vendored bindings never
 # drift from the wire format the backend and Python SDK share. This mirrors the
diff --git a/proto/event.proto b/proto/event.proto
index 35d9a48..1281cbe 100644
--- a/proto/event.proto
+++ b/proto/event.proto
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 syntax = "proto3";
 
 package adrian.core_api.v1;
diff --git a/scripts/add_license_header.py b/scripts/add_license_header.py
new file mode 100644
index 0000000..a5826bb
--- /dev/null
+++ b/scripts/add_license_header.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+"""Prepend the Apache-2.0 SPDX header to source files that lack one.
+
+Invoked by pre-commit with the staged filenames; scoping (which trees,
+which extensions, vendored and generated files excluded) lives in
+.pre-commit-config.yaml. Exits 1 when any file was modified so the
+commit aborts and the fixed files can be reviewed and re-staged.
+"""
+
+from __future__ import annotations
+
+import re
+import sys
+from pathlib import Path
+
+SPDX = "SPDX-License-Identifier: Apache-2.0"
+COPYRIGHT = "Copyright (c) 2026 SecureAgentics"
+
+SLASH_SUFFIXES = {".go", ".ts", ".tsx", ".js", ".mjs", ".cjs", ".proto"}
+HASH_SUFFIXES = {".py", ".pyi", ".sh"}
+
+ENCODING_DECL = re.compile(r"^[ \t\f]*#.*?coding[:=]")
+
+
+def insertion_index(lines: list[str], path: Path) -> int:
+    """Return the line index where the header goes.
+
+    Skips a shebang and, for Python files, a PEP 263 encoding declaration
+    (both must stay in the first two lines).
+    """
+    i = 0
+    if lines and lines[0].startswith("#!"):
+        i = 1
+    if (
+        path.suffix in {".py", ".pyi"}
+        and len(lines) > i
+        and ENCODING_DECL.match(lines[i])
+    ):
+        i += 1
+    return i
+
+
+def add_header(path: Path) -> bool:
+    """Prepend the header to path if missing; return True when modified."""
+    if path.suffix in SLASH_SUFFIXES:
+        prefix = "//"
+    elif path.suffix in HASH_SUFFIXES:
+        prefix = "#"
+    else:
+        return False
+    text = path.read_text(encoding="utf-8")
+    if SPDX in "".join(text.splitlines(keepends=True)[:5]):
+        return False
+    lines = text.splitlines(keepends=True)
+    i = insertion_index(lines, path)
+    header = f"{prefix} {SPDX}\n{prefix} {COPYRIGHT}\n"
+    rest = "".join(lines[i:])
+    if rest and not rest.startswith(("\n", "\r")):
+        header += "\n"
+    path.write_text("".join(lines[:i]) + header + rest, encoding="utf-8")
+    return True
+
+
+def main(argv: list[str]) -> int:
+    """Process every file named in argv; return 1 when any was changed."""
+    changed = [name for name in argv if add_header(Path(name))]
+    for name in changed:
+        print(f"added licence header: {name}")
+    return 1 if changed else 0
+
+
+if __name__ == "__main__":
+    raise SystemExit(main(sys.argv[1:]))
diff --git a/scripts/setup.py b/scripts/setup.py
index 491c1ed..3d29e33 100644
--- a/scripts/setup.py
+++ b/scripts/setup.py
@@ -1,4 +1,7 @@
 #!/usr/bin/env python3
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian bootstrap utility.
 
 Runs inside the `adrian-setup` container. Initialises the SQLite
diff --git a/sdk/python/adrian/__init__.py b/sdk/python/adrian/__init__.py
index 2cb0d23..66f2f17 100644
--- a/sdk/python/adrian/__init__.py
+++ b/sdk/python/adrian/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian: multi-agent event capture SDK for LangChain/LangGraph as of 2026-05-10.
 
 Initialise with a single call and all LLM / tool activity is automatically
diff --git a/sdk/python/adrian/adapters/__init__.py b/sdk/python/adrian/adapters/__init__.py
index 5198076..debc472 100644
--- a/sdk/python/adrian/adapters/__init__.py
+++ b/sdk/python/adrian/adapters/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Framework-specific adapters for agent identity detection."""
diff --git a/sdk/python/adrian/adapters/langgraph.py b/sdk/python/adrian/adapters/langgraph.py
index 745c74d..e60e29c 100644
--- a/sdk/python/adrian/adapters/langgraph.py
+++ b/sdk/python/adrian/adapters/langgraph.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """LangGraph adapter for agent identity detection.
 
 Parses the ``langgraph_checkpoint_ns`` (checkpoint namespace) field from
diff --git a/sdk/python/adrian/callbacks.py b/sdk/python/adrian/callbacks.py
index a1bff71..a84bf6c 100644
--- a/sdk/python/adrian/callbacks.py
+++ b/sdk/python/adrian/callbacks.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Centralised callback firing helper.
 
 The SDK has a family of optional user-supplied callbacks (``on_event``,
diff --git a/sdk/python/adrian/config.py b/sdk/python/adrian/config.py
index 238b54c..a118888 100644
--- a/sdk/python/adrian/config.py
+++ b/sdk/python/adrian/config.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian SDK configuration.
 
 Transport (WebSocket, HTTP) is not managed by the SDK, it is handled
diff --git a/sdk/python/adrian/context.py b/sdk/python/adrian/context.py
index 9231566..ec8dc77 100644
--- a/sdk/python/adrian/context.py
+++ b/sdk/python/adrian/context.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Invocation and agent context tracking.
 
 Tracks two concepts that LangChain's callback system does not provide:
diff --git a/sdk/python/adrian/format/__init__.py b/sdk/python/adrian/format/__init__.py
index c348eae..c9d8063 100644
--- a/sdk/python/adrian/format/__init__.py
+++ b/sdk/python/adrian/format/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian unified event format.
 
 Defines the ``PairedEvent`` data model that combines start+end LangChain
diff --git a/sdk/python/adrian/format/types.py b/sdk/python/adrian/format/types.py
index 1fd1e80..7541b84 100644
--- a/sdk/python/adrian/format/types.py
+++ b/sdk/python/adrian/format/types.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Adrian unified event format types.
 
 Each LangChain callback pair (chat_model_start + llm_end, or tool_start +
diff --git a/sdk/python/adrian/handler.py b/sdk/python/adrian/handler.py
index 3289041..166b7d2 100644
--- a/sdk/python/adrian/handler.py
+++ b/sdk/python/adrian/handler.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """LangChain async callback handler that produces Adrian PairedEvents.
 
 Captures five LangChain callback events, pairs them (chat_model_start +
diff --git a/sdk/python/adrian/handlers/__init__.py b/sdk/python/adrian/handlers/__init__.py
index 4571515..c425361 100644
--- a/sdk/python/adrian/handlers/__init__.py
+++ b/sdk/python/adrian/handlers/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Built-in event handler implementations."""
 
 from adrian.handlers.jsonl import JSONLHandler
diff --git a/sdk/python/adrian/handlers/jsonl.py b/sdk/python/adrian/handlers/jsonl.py
index d2825fa..3063094 100644
--- a/sdk/python/adrian/handlers/jsonl.py
+++ b/sdk/python/adrian/handlers/jsonl.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """JSONL file handler for paired events.
 
 Writes each ``PairedEvent`` as a single JSON line to a file. This is
diff --git a/sdk/python/adrian/hooks.py b/sdk/python/adrian/hooks.py
index 4ee4976..8fcc8f2 100644
--- a/sdk/python/adrian/hooks.py
+++ b/sdk/python/adrian/hooks.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Handler hook registry.
 
 Decouples event transport from event capture. The SDK captures and
diff --git a/sdk/python/adrian/identity.py b/sdk/python/adrian/identity.py
index c8345bd..3de64a5 100644
--- a/sdk/python/adrian/identity.py
+++ b/sdk/python/adrian/identity.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Agent identity dispatcher.
 
 Derives an ``agent_id`` from callback metadata using framework-specific
diff --git a/sdk/python/adrian/mcp.py b/sdk/python/adrian/mcp.py
index b41eae9..8101752 100644
--- a/sdk/python/adrian/mcp.py
+++ b/sdk/python/adrian/mcp.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """MCP server tracking for LangChain agents.
 
 Maintains a per-process aggregate of the MCP servers an agent is
diff --git a/sdk/python/adrian/pairing.py b/sdk/python/adrian/pairing.py
index 717b82c..be63728 100644
--- a/sdk/python/adrian/pairing.py
+++ b/sdk/python/adrian/pairing.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Event pair buffer.
 
 Buffers start events (chat_model_start, tool_start) and assembles
diff --git a/sdk/python/adrian/pii/__init__.py b/sdk/python/adrian/pii/__init__.py
index d35270a..3643f79 100644
--- a/sdk/python/adrian/pii/__init__.py
+++ b/sdk/python/adrian/pii/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """PII detection and redaction for Adrian events.
 
 Provides standalone ``redact_text()`` for arbitrary strings and
diff --git a/sdk/python/adrian/pii/_engine.py b/sdk/python/adrian/pii/_engine.py
index d3c4de8..0c90eae 100644
--- a/sdk/python/adrian/pii/_engine.py
+++ b/sdk/python/adrian/pii/_engine.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Standalone PII detection and redaction engine.
 
 Provides ``redact_text``, usable independently of the Adrian SDK.
diff --git a/sdk/python/adrian/pii/_patterns.py b/sdk/python/adrian/pii/_patterns.py
index 8f13c39..4da71f0 100644
--- a/sdk/python/adrian/pii/_patterns.py
+++ b/sdk/python/adrian/pii/_patterns.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """PII detection patterns.
 
 Compiled regex patterns for common PII types found in AI agent
diff --git a/sdk/python/adrian/pii/_redactor.py b/sdk/python/adrian/pii/_redactor.py
index cad0703..9f99e91 100644
--- a/sdk/python/adrian/pii/_redactor.py
+++ b/sdk/python/adrian/pii/_redactor.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """PairedEvent PII redactor.
 
 Applies PII redaction to text fields within a ``PairedEvent``'s
diff --git a/sdk/python/adrian/pii/_strategies.py b/sdk/python/adrian/pii/_strategies.py
index 1037504..86f3eba 100644
--- a/sdk/python/adrian/pii/_strategies.py
+++ b/sdk/python/adrian/pii/_strategies.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """PII redaction strategies.
 
 Each strategy transforms a ``Detection``'s matched text into a
diff --git a/sdk/python/adrian/proto/__init__.py b/sdk/python/adrian/proto/__init__.py
index 34f2f99..5cabae2 100644
--- a/sdk/python/adrian/proto/__init__.py
+++ b/sdk/python/adrian/proto/__init__.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Vendored protobuf definitions for the Adrian Worker Core API wire format."""
 
 # Pre-load Google well-known types into the descriptor pool before
diff --git a/sdk/python/adrian/proto/buf/__init__.py b/sdk/python/adrian/proto/buf/__init__.py
index 5838411..7a1f6b4 100644
--- a/sdk/python/adrian/proto/buf/__init__.py
+++ b/sdk/python/adrian/proto/buf/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Vendored buf.validate protobuf stubs."""
diff --git a/sdk/python/adrian/proto/buf/validate/__init__.py b/sdk/python/adrian/proto/buf/validate/__init__.py
index 265ad6d..f05860b 100644
--- a/sdk/python/adrian/proto/buf/validate/__init__.py
+++ b/sdk/python/adrian/proto/buf/validate/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Vendored buf.validate protobuf validation stubs."""
diff --git a/sdk/python/adrian/session_persistence.py b/sdk/python/adrian/session_persistence.py
index 0f88429..7b11d57 100644
--- a/sdk/python/adrian/session_persistence.py
+++ b/sdk/python/adrian/session_persistence.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Persistent per-cwd session_id storage.
 
 By default Adrian assigns a fresh ``session_id`` on every SDK init,
diff --git a/sdk/python/adrian/types.py b/sdk/python/adrian/types.py
index 13c1506..b934a17 100644
--- a/sdk/python/adrian/types.py
+++ b/sdk/python/adrian/types.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Typed event schema for Adrian SDK.
 
 Defines TypedDict classes matching the Adrian protobuf schema.  These serve as
diff --git a/sdk/python/adrian/ws.py b/sdk/python/adrian/ws.py
index 9b26d70..c79bd7f 100644
--- a/sdk/python/adrian/ws.py
+++ b/sdk/python/adrian/ws.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Async WebSocket ``EventHandler`` that streams ``PairedEvent`` to the worker core API.
 
 Converts each ``PairedEvent`` into a ``pb.PairedEvent`` protobuf, wraps it in a
diff --git a/sdk/python/tests/__init__.py b/sdk/python/tests/__init__.py
index fe70945..3a66955 100644
--- a/sdk/python/tests/__init__.py
+++ b/sdk/python/tests/__init__.py
@@ -1 +1,4 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for Adrian SDK."""
diff --git a/sdk/python/tests/test_block_mode.py b/sdk/python/tests/test_block_mode.py
index 742249b..949cdb2 100644
--- a/sdk/python/tests/test_block_mode.py
+++ b/sdk/python/tests/test_block_mode.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for the patched ``ToolNode`` halt path in ``MODE_BLOCK``."""
 
 # pyright: reportPrivateUsage=false
diff --git a/sdk/python/tests/test_block_mode_races.py b/sdk/python/tests/test_block_mode_races.py
index 394408d..171b775 100644
--- a/sdk/python/tests/test_block_mode_races.py
+++ b/sdk/python/tests/test_block_mode_races.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Block-mode correctness tests under multi-agent scenarios.
 
 Each test simulates the PairedEvent stream that each S1-S8 scenario would
diff --git a/sdk/python/tests/test_exec_modes.py b/sdk/python/tests/test_exec_modes.py
index f3f5e42..936830f 100644
--- a/sdk/python/tests/test_exec_modes.py
+++ b/sdk/python/tests/test_exec_modes.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """End-to-end execution-mode coverage.
 
 Drives the SDK through each of the three server-supplied modes and the
diff --git a/sdk/python/tests/test_handler.py b/sdk/python/tests/test_handler.py
index cc421ec..eed45f6 100644
--- a/sdk/python/tests/test_handler.py
+++ b/sdk/python/tests/test_handler.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.handler.AdrianCallbackHandler (new PairedEvent flow)."""
 
 from __future__ import annotations
diff --git a/sdk/python/tests/test_init.py b/sdk/python/tests/test_init.py
index 17dc6e6..ee4c275 100644
--- a/sdk/python/tests/test_init.py
+++ b/sdk/python/tests/test_init.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.init / shutdown and auto-instrumentation."""
 
 # pyright: reportPrivateUsage=false
diff --git a/sdk/python/tests/test_mcp.py b/sdk/python/tests/test_mcp.py
index fdd456f..1a609f5 100644
--- a/sdk/python/tests/test_mcp.py
+++ b/sdk/python/tests/test_mcp.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.mcp, MCP server tracking via langchain-mcp-adapters."""
 
 from __future__ import annotations
diff --git a/sdk/python/tests/test_parent_context_scenarios.py b/sdk/python/tests/test_parent_context_scenarios.py
index 327884b..4d9f8c5 100644
--- a/sdk/python/tests/test_parent_context_scenarios.py
+++ b/sdk/python/tests/test_parent_context_scenarios.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """End-to-end parent-context derivation per multi-agent scenario (S1-S8).
 
 Fires the LangChain-shaped callback sequence each scenario produces -
diff --git a/sdk/python/tests/test_pii_engine.py b/sdk/python/tests/test_pii_engine.py
index e3eb56d..a983a10 100644
--- a/sdk/python/tests/test_pii_engine.py
+++ b/sdk/python/tests/test_pii_engine.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.pii._engine, redact_text standalone function."""
 
 from __future__ import annotations
diff --git a/sdk/python/tests/test_pii_integration.py b/sdk/python/tests/test_pii_integration.py
index b93f88c..c8d52b9 100644
--- a/sdk/python/tests/test_pii_integration.py
+++ b/sdk/python/tests/test_pii_integration.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Integration tests for always-on PII redaction in adrian.init()."""
 
 # pyright: reportPrivateUsage=false
diff --git a/sdk/python/tests/test_pii_patterns.py b/sdk/python/tests/test_pii_patterns.py
index 8049d03..a898cb9 100644
--- a/sdk/python/tests/test_pii_patterns.py
+++ b/sdk/python/tests/test_pii_patterns.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.pii._patterns, per-PII-type detection."""
 
 from __future__ import annotations
diff --git a/sdk/python/tests/test_pii_redactor.py b/sdk/python/tests/test_pii_redactor.py
index 9965e97..fcf7b29 100644
--- a/sdk/python/tests/test_pii_redactor.py
+++ b/sdk/python/tests/test_pii_redactor.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.pii._redactor, PairedEvent redaction."""
 
 from __future__ import annotations
diff --git a/sdk/python/tests/test_resilience.py b/sdk/python/tests/test_resilience.py
index 48cfd9c..be5e43c 100644
--- a/sdk/python/tests/test_resilience.py
+++ b/sdk/python/tests/test_resilience.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for the in-memory replay buffer and reconnect replay path.
 
 Key design: the happy path (connected + send succeeds) does NOT touch the
diff --git a/sdk/python/tests/test_session_persistence.py b/sdk/python/tests/test_session_persistence.py
index de3180f..2ee5285 100644
--- a/sdk/python/tests/test_session_persistence.py
+++ b/sdk/python/tests/test_session_persistence.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for adrian.session_persistence, per-cwd session_id storage."""
 
 # pyright: reportPrivateUsage=false
diff --git a/sdk/python/tests/test_ws.py b/sdk/python/tests/test_ws.py
index c28762e..744331a 100644
--- a/sdk/python/tests/test_ws.py
+++ b/sdk/python/tests/test_ws.py
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 """Tests for the WebSocket client, new PairedEvent format."""
 
 # pyright: reportPrivateUsage=false
diff --git a/sdk/python/tools/regen-proto.sh b/sdk/python/tools/regen-proto.sh
index 3ba08bb..b97e5f1 100755
--- a/sdk/python/tools/regen-proto.sh
+++ b/sdk/python/tools/regen-proto.sh
@@ -1,4 +1,7 @@
 #!/usr/bin/env bash
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2026 SecureAgentics
+
 # Regenerate adrian/proto/event_pb2.py and event_pb2.pyi from event.proto.
 #
 # The SDK vendors the generated buf.validate Python bindings at
diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json
index cc273d4..924fa25 100644
--- a/sdk/typescript/package.json
+++ b/sdk/typescript/package.json
@@ -1,6 +1,7 @@
 {
   "name": "@secureagentics/adrian-workspace",
   "private": true,
+  "license": "Apache-2.0",
   "description": "Adrian TypeScript SDK monorepo (npm workspaces).",
   "workspaces": [
     "packages/*"
diff --git a/sdk/typescript/packages/core/src/capture/common.ts b/sdk/typescript/packages/core/src/capture/common.ts
index a51baf9..8ae18ba 100644
--- a/sdk/typescript/packages/core/src/capture/common.ts
+++ b/sdk/typescript/packages/core/src/capture/common.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { randomUUID } from "node:crypto";
 import type { AdrianCallbackHandler } from "../handler.js";
 import { getInvocationId, runWithInvocationId } from "../context.js";
diff --git a/sdk/typescript/packages/core/src/capture/index.ts b/sdk/typescript/packages/core/src/capture/index.ts
index e9db7b2..5aaa311 100644
--- a/sdk/typescript/packages/core/src/capture/index.ts
+++ b/sdk/typescript/packages/core/src/capture/index.ts
@@ -1 +1,4 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 export * from "./common.js";
diff --git a/sdk/typescript/packages/core/src/config.ts b/sdk/typescript/packages/core/src/config.ts
index 8a9e1dc..59e0e0d 100644
--- a/sdk/typescript/packages/core/src/config.ts
+++ b/sdk/typescript/packages/core/src/config.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { EventData, McpServer, VerdictContext } from "./types.js";
 
 export type MaybePromise = T | Promise;
diff --git a/sdk/typescript/packages/core/src/context.ts b/sdk/typescript/packages/core/src/context.ts
index 0ad59db..3b1fbd8 100644
--- a/sdk/typescript/packages/core/src/context.ts
+++ b/sdk/typescript/packages/core/src/context.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { AsyncLocalStorage } from "node:async_hooks";
 import type { AgentContext, ParentContext } from "./format/types.js";
 
diff --git a/sdk/typescript/packages/core/src/format/types.ts b/sdk/typescript/packages/core/src/format/types.ts
index cc262cf..bb540cb 100644
--- a/sdk/typescript/packages/core/src/format/types.ts
+++ b/sdk/typescript/packages/core/src/format/types.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { CallbackMetadata, ChatMessage, ErrorData, TokenUsage, ToolCallRecord } from "../types.js";
 
 export interface AgentContext {
diff --git a/sdk/typescript/packages/core/src/handler.ts b/sdk/typescript/packages/core/src/handler.ts
index 1c5310a..95955c3 100644
--- a/sdk/typescript/packages/core/src/handler.ts
+++ b/sdk/typescript/packages/core/src/handler.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { currentConfig, type AdrianConfig } from "./config.js";
 import { getInvocationId } from "./context.js";
 import { AgentContextTracker } from "./context.js";
diff --git a/sdk/typescript/packages/core/src/handlers/jsonl.ts b/sdk/typescript/packages/core/src/handlers/jsonl.ts
index 25e3be5..0c4ef9f 100644
--- a/sdk/typescript/packages/core/src/handlers/jsonl.ts
+++ b/sdk/typescript/packages/core/src/handlers/jsonl.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { mkdir, open, type FileHandle } from "node:fs/promises";
 import { dirname } from "node:path";
 import type { PairedEvent } from "../format/types.js";
diff --git a/sdk/typescript/packages/core/src/hooks.ts b/sdk/typescript/packages/core/src/hooks.ts
index 759b172..c376f48 100644
--- a/sdk/typescript/packages/core/src/hooks.ts
+++ b/sdk/typescript/packages/core/src/hooks.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { PairedEvent } from "./format/types.js";
 import type { EventHandler } from "./types.js";
 
diff --git a/sdk/typescript/packages/core/src/identity.ts b/sdk/typescript/packages/core/src/identity.ts
index 019352b..72c02ec 100644
--- a/sdk/typescript/packages/core/src/identity.ts
+++ b/sdk/typescript/packages/core/src/identity.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { CallbackMetadata, ChatMessage } from "./types.js";
 
 export function deriveAgentId(_metadata: CallbackMetadata | null, _messages?: ChatMessage[] | null): string {
diff --git a/sdk/typescript/packages/core/src/index.ts b/sdk/typescript/packages/core/src/index.ts
index ec5305f..0e4854f 100644
--- a/sdk/typescript/packages/core/src/index.ts
+++ b/sdk/typescript/packages/core/src/index.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { resolveInitOptions, setConfig, type AdrianConfig, type InitOptions } from "./config.js";
 import { AgentContextTracker } from "./context.js";
 import { AdrianCallbackHandler } from "./handler.js";
diff --git a/sdk/typescript/packages/core/src/mcp.ts b/sdk/typescript/packages/core/src/mcp.ts
index 421519c..10dad1e 100644
--- a/sdk/typescript/packages/core/src/mcp.ts
+++ b/sdk/typescript/packages/core/src/mcp.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { currentConfig, isInitialized } from "./config.js";
 import type { McpServer } from "./types.js";
 
diff --git a/sdk/typescript/packages/core/src/pairing.ts b/sdk/typescript/packages/core/src/pairing.ts
index 9e70f3d..9a659cf 100644
--- a/sdk/typescript/packages/core/src/pairing.ts
+++ b/sdk/typescript/packages/core/src/pairing.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { randomUUID } from "node:crypto";
 import type { AgentContext, PairedEvent, ParentContext } from "./format/types.js";
 import type { CallbackMetadata, ChatModelStartData, LlmEndData, ToolEndData, ToolStartData } from "./types.js";
diff --git a/sdk/typescript/packages/core/src/pii/engine.ts b/sdk/typescript/packages/core/src/pii/engine.ts
index b580a47..6358c3f 100644
--- a/sdk/typescript/packages/core/src/pii/engine.ts
+++ b/sdk/typescript/packages/core/src/pii/engine.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { detect, type Detection, type PiiType } from "./patterns.js";
 import { applyStrategy, RedactionStrategy } from "./strategies.js";
 
diff --git a/sdk/typescript/packages/core/src/pii/index.ts b/sdk/typescript/packages/core/src/pii/index.ts
index 04b17c2..b0d3790 100644
--- a/sdk/typescript/packages/core/src/pii/index.ts
+++ b/sdk/typescript/packages/core/src/pii/index.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 export { redactText } from "./engine.js";
 export type { PiiConfig, RedactionResult } from "./engine.js";
 export { PiiType, detect } from "./patterns.js";
diff --git a/sdk/typescript/packages/core/src/pii/patterns.ts b/sdk/typescript/packages/core/src/pii/patterns.ts
index 3f89ce0..65f9be0 100644
--- a/sdk/typescript/packages/core/src/pii/patterns.ts
+++ b/sdk/typescript/packages/core/src/pii/patterns.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { isIP } from "node:net";
 
 export enum PiiType {
diff --git a/sdk/typescript/packages/core/src/pii/redactor.ts b/sdk/typescript/packages/core/src/pii/redactor.ts
index b59d559..4ce2527 100644
--- a/sdk/typescript/packages/core/src/pii/redactor.ts
+++ b/sdk/typescript/packages/core/src/pii/redactor.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { PairedEvent } from "../format/types.js";
 import type { EventHandler, JsonValue } from "../types.js";
 import { redactText, type PiiConfig } from "./engine.js";
diff --git a/sdk/typescript/packages/core/src/pii/strategies.ts b/sdk/typescript/packages/core/src/pii/strategies.ts
index f735229..315e8b4 100644
--- a/sdk/typescript/packages/core/src/pii/strategies.ts
+++ b/sdk/typescript/packages/core/src/pii/strategies.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { createHash } from "node:crypto";
 import { Detection, PiiType } from "./patterns.js";
 
diff --git a/sdk/typescript/packages/core/src/policy.ts b/sdk/typescript/packages/core/src/policy.ts
index 9c05519..c715cdd 100644
--- a/sdk/typescript/packages/core/src/policy.ts
+++ b/sdk/typescript/packages/core/src/policy.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { currentConfig } from "./config.js";
 import { shouldHalt, type WebSocketClient } from "./ws.js";
 
diff --git a/sdk/typescript/packages/core/src/proto/schema.ts b/sdk/typescript/packages/core/src/proto/schema.ts
index f5d886b..818a722 100644
--- a/sdk/typescript/packages/core/src/proto/schema.ts
+++ b/sdk/typescript/packages/core/src/proto/schema.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import protobuf from "protobufjs";
 import type { PairedEvent } from "../format/types.js";
 import type { McpServer } from "../types.js";
diff --git a/sdk/typescript/packages/core/src/registry.ts b/sdk/typescript/packages/core/src/registry.ts
index 191c0bb..1f858d1 100644
--- a/sdk/typescript/packages/core/src/registry.ts
+++ b/sdk/typescript/packages/core/src/registry.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { AdrianCallbackHandler } from "./handler.js";
 import type { WebSocketClient } from "./ws.js";
 
diff --git a/sdk/typescript/packages/core/src/sessionPersistence.ts b/sdk/typescript/packages/core/src/sessionPersistence.ts
index 92d5dca..b7ef154 100644
--- a/sdk/typescript/packages/core/src/sessionPersistence.ts
+++ b/sdk/typescript/packages/core/src/sessionPersistence.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { randomUUID } from "node:crypto";
 import { mkdir, readFile, writeFile } from "node:fs/promises";
 import { homedir } from "node:os";
diff --git a/sdk/typescript/packages/core/src/types.ts b/sdk/typescript/packages/core/src/types.ts
index c8c0ceb..7f4a426 100644
--- a/sdk/typescript/packages/core/src/types.ts
+++ b/sdk/typescript/packages/core/src/types.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import type { PairedEvent } from "./format/types.js";
 import type { PolicySnapshot, HitlResponse } from "./proto/schema.js";
 
diff --git a/sdk/typescript/packages/core/src/ws.ts b/sdk/typescript/packages/core/src/ws.ts
index 4715668..c32c3b1 100644
--- a/sdk/typescript/packages/core/src/ws.ts
+++ b/sdk/typescript/packages/core/src/ws.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import WebSocket from "ws";
 import type { AdrianCallbackHandler } from "./handler.js";
 import type { PairedEvent } from "./format/types.js";
diff --git a/sdk/typescript/packages/core/tests/capture.test.ts b/sdk/typescript/packages/core/tests/capture.test.ts
index f6c0c04..9946855 100644
--- a/sdk/typescript/packages/core/tests/capture.test.ts
+++ b/sdk/typescript/packages/core/tests/capture.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { describe, expect, it } from "vitest";
 import { messagesFromPromptLike, normalizeResponseInput } from "../src/capture/common.js";
 
diff --git a/sdk/typescript/packages/core/tests/init.test.ts b/sdk/typescript/packages/core/tests/init.test.ts
index a90f66e..ea2be6f 100644
--- a/sdk/typescript/packages/core/tests/init.test.ts
+++ b/sdk/typescript/packages/core/tests/init.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { afterEach, describe, expect, it, vi } from "vitest";
 import { currentConfig, resolveInitOptions } from "../src/config.js";
 import { getWebSocketClient, init, shutdown } from "../src/index.js";
diff --git a/sdk/typescript/packages/core/tests/jsonl.test.ts b/sdk/typescript/packages/core/tests/jsonl.test.ts
index 9c10c51..6faeadf 100644
--- a/sdk/typescript/packages/core/tests/jsonl.test.ts
+++ b/sdk/typescript/packages/core/tests/jsonl.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { mkdtemp, readFile } from "node:fs/promises";
 import { tmpdir } from "node:os";
 import { join } from "node:path";
diff --git a/sdk/typescript/packages/core/tests/pairing.test.ts b/sdk/typescript/packages/core/tests/pairing.test.ts
index 9e50a06..9bc3bac 100644
--- a/sdk/typescript/packages/core/tests/pairing.test.ts
+++ b/sdk/typescript/packages/core/tests/pairing.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { describe, expect, it } from "vitest";
 import { EventPairBuffer } from "../src/pairing.js";
 
diff --git a/sdk/typescript/packages/core/tests/pii.test.ts b/sdk/typescript/packages/core/tests/pii.test.ts
index 035d201..1503333 100644
--- a/sdk/typescript/packages/core/tests/pii.test.ts
+++ b/sdk/typescript/packages/core/tests/pii.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { describe, expect, it } from "vitest";
 import { redactText, PiiType, RedactionStrategy } from "../src/pii/index.js";
 import { applyStrategy } from "../src/pii/strategies.js";
diff --git a/sdk/typescript/packages/core/tests/policy.test.ts b/sdk/typescript/packages/core/tests/policy.test.ts
index d469b85..07058ea 100644
--- a/sdk/typescript/packages/core/tests/policy.test.ts
+++ b/sdk/typescript/packages/core/tests/policy.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { afterEach, describe, expect, it } from "vitest";
 import { setConfig, Mode, type Verdict, type WebSocketClient } from "../src/index.js";
 import { assertToolCallsAllowed, gateToolCallIds } from "../src/policy.js";
diff --git a/sdk/typescript/packages/core/tests/proto.test.ts b/sdk/typescript/packages/core/tests/proto.test.ts
index 9776de1..0a531ca 100644
--- a/sdk/typescript/packages/core/tests/proto.test.ts
+++ b/sdk/typescript/packages/core/tests/proto.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { describe, expect, it } from "vitest";
 import { encodeClientFrame, SCHEMA_VERSION } from "../src/proto/schema.js";
 import type { PairedEvent } from "../src/format/types.js";
diff --git a/sdk/typescript/packages/core/tests/session.test.ts b/sdk/typescript/packages/core/tests/session.test.ts
index 2ba7bf5..1de3558 100644
--- a/sdk/typescript/packages/core/tests/session.test.ts
+++ b/sdk/typescript/packages/core/tests/session.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { describe, expect, it } from "vitest";
 import { cwdKey } from "../src/sessionPersistence.js";
 
diff --git a/sdk/typescript/packages/core/tests/ws.test.ts b/sdk/typescript/packages/core/tests/ws.test.ts
index 734db4f..e46f950 100644
--- a/sdk/typescript/packages/core/tests/ws.test.ts
+++ b/sdk/typescript/packages/core/tests/ws.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
 import type { PairedEvent } from "../src/format/types.js";
 import { Mode, type Verdict } from "../src/proto/schema.js";
diff --git a/sdk/typescript/packages/core/tsup.config.ts b/sdk/typescript/packages/core/tsup.config.ts
index 7dc6415..68e697f 100644
--- a/sdk/typescript/packages/core/tsup.config.ts
+++ b/sdk/typescript/packages/core/tsup.config.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { readFileSync } from "node:fs";
 import { defineConfig } from "tsup";
 
diff --git a/sdk/typescript/packages/openai/src/index.ts b/sdk/typescript/packages/openai/src/index.ts
index 80244aa..4b563f3 100644
--- a/sdk/typescript/packages/openai/src/index.ts
+++ b/sdk/typescript/packages/openai/src/index.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { randomUUID } from "node:crypto";
 import {
   BLOCKED_TOOL_MESSAGE,
diff --git a/sdk/typescript/packages/openai/tests/openai.test.ts b/sdk/typescript/packages/openai/tests/openai.test.ts
index bd6d455..ed51012 100644
--- a/sdk/typescript/packages/openai/tests/openai.test.ts
+++ b/sdk/typescript/packages/openai/tests/openai.test.ts
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (c) 2026 SecureAgentics
+
 import { afterEach, describe, expect, it, vi } from "vitest";
 import * as adrianCore from "@secureagentics/adrian";
 import { BLOCKED_TOOL_MESSAGE, Mode, type EventData, type PairedEvent, type Verdict, type WebSocketClient } from "@secureagentics/adrian";