chore: relicense to AGPL-3.0-or-later and add SPDX headers

Replaces LICENSE (GPLv3 -> AGPLv3) and prepends
`SPDX-License-Identifier: AGPL-3.0-or-later` to every source file
across decnet/, decnet_web/, tests/, scripts/, and tools/.

Rationale: closes the GPLv3 ASP loophole so any party operating a
modified DECNET as a network service must offer their modified
source. Personal copyright (Samuel Paschuan) + inbound=outbound
contributions make a future unilateral relicense infeasible.

- LICENSE: full AGPL-3.0 text (gnu.org/licenses/agpl-3.0.txt)
- COPYRIGHT: project copyright notice
- tools/add_spdx_headers.py: idempotent header injector
  (shebang- and PEP 263-aware)

Touches 1565 source files (.py, .ts, .tsx, .js, .jsx, .css, .sh).
No behavior change; comments only.
This commit is contained in:
2026-05-22 21:04:16 -04:00
parent ee10b55cfe
commit f2b3393669
1563 changed files with 1810 additions and 77 deletions

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.counter {
font-size: 16px;
padding: 5px 10px;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { lazy, Suspense, useState, useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate, useNavigate } from 'react-router-dom';
import Login from './components/Login';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import api from '../utils/api';
import Modal from './Modal/Modal';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { X, Download, AlertTriangle } from '../icons';
import api from '../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import { AlertTriangle, Eye, Shield } from '../../../icons';
import api from '../../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export const VERDICT_TONE: Record<string, { color: string; label: string }> = {
malicious: { color: 'var(--alert)', label: 'MALICIOUS' },
suspicious: { color: 'var(--warn)', label: 'SUSPICIOUS' },

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export { IntelPanel } from './IntelPanel';
export { VERDICT_TONE, fmtTs } from './helpers';
export type { IntelRow } from './types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/* eslint-disable @typescript-eslint/no-explicit-any */
// Mirrors decnet/web/db/models/attacker_intel.py — server returns the row

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import EmptyState from '../../EmptyState/EmptyState';
import { Activity } from '../../../icons';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export { BehaviouralPrimitivesPanel } from './BehaviouralPrimitivesPanel';
export {
BehaviorHeadline, BeaconBlock, DetectedToolsBlock, PhaseSequenceBlock,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type React from 'react';
import {
Activity, Clock, Cpu, Globe, Keyboard, Sparkles,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import {
Activity, Crosshair, Radio, Timer, Wifi,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import {
Clock, Crosshair, FileKey, Fingerprint, Lock, Shield, Wifi,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export { FingerprintGroup } from './renderers';
export {
FpTlsHashes, FpLatency, FpResumption, FpCertificate, FpJarm,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { Fingerprint } from '../../../icons';
import { Tag } from '../ui';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { Package, Paperclip } from '../../../icons';
import EmptyState from '../../EmptyState/EmptyState';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Crosshair, Download } from '../../../icons';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { makeAttacker } from '../../../test/fixtures';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import type { AttackerData } from '../types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { ChevronLeft, ChevronRight, Terminal } from '../../../icons';
import EmptyState from '../../EmptyState/EmptyState';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { Mail } from '../../../icons';
import EmptyState from '../../EmptyState/EmptyState';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { Section } from '../ui';
import type { AttackerData } from '../types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { Section, Tag } from '../ui';
import type { AttackerData } from '../types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/** Shared types for the AttackerDetail page surface. The canonical
* definitions live here; AttackerDetail.tsx re-exports the public
* ones (BehaviouralObservation, AttributionPrimitiveState) so

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { ChevronDown, ChevronUp } from '../../icons';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { useEffect, useState } from 'react';
import api from '../../utils/api';
import { useIdentityStream } from '../useIdentityStream';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.attackers-root {
display: flex;
flex-direction: column;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { Search, ChevronLeft, ChevronRight, Users, Download } from '../icons';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.bounty-root {
display: flex;
flex-direction: column;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { X, Key, Package, Copy, Send, Ban, FileText, Mail, Download, AlertTriangle } from '../icons';
import { useToast } from './Toasts/useToast';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { ArrowLeft, Crosshair, Filter, Fingerprint, Globe, Radio } from '../icons';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { X, Download, AlertTriangle, Trash2, Eye } from '../icons';
import api from '../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import { Plus, Upload, Target } from '../icons';
import CanaryTokenDrawer from './CanaryTokenDrawer';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import type { BlobRow } from './types';
import { fmt, fmtBytes } from './helpers';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { X } from '../../icons';
import api from '../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import type { FileDropEntry } from './FileDropModal';
import { fmt, fmtBytes } from './helpers';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useRef, useState } from 'react';
import { Upload, X, AlertTriangle } from '../../icons';
import api from '../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useMemo } from 'react';
import { Search } from '../../icons';
import type { CanaryTokenRow } from '../CanaryTokenDrawer';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useRef, useState } from 'react';
import { Upload, X, AlertTriangle } from '../../icons';
import api from '../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type { ApiError } from '../../utils/api';
/** Normalize an axios error into operator-friendly text, with role

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/** Wire + UI types for the CanaryTokens page surface. */
export interface BlobRow {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
export const INPUT_STYLE: React.CSSProperties = {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { useCallback, useEffect, useMemo, useState } from 'react';
import api from '../../utils/api';
import type { CanaryTokenRow } from '../CanaryTokenDrawer';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.cmd-backdrop {
position: fixed;
inset: 0;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
LayoutDashboard, Server, Network, Terminal, Archive, Crosshair,

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.config-page {
display: flex;
flex-direction: column;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import {
Settings, Users, Sliders, Shield, Palette, Activity, Cpu,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { http, HttpResponse, server, apiUrl } from '../../test/server';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import { AlertTriangle, Play, RefreshCw, Square } from '../../icons';
import api from '../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { useToast } from '../../Toasts/useToast';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { AlertTriangle, Save, Trash2 } from '../../../icons';
import type { FormMsg } from '../types';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
/* LLMTab — layered on DeckyFleet.css + PersonaGeneration.css.
Scoped to .llm-tab-root. Same vocabulary as the old standalone page. */

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useState } from 'react';
import { Save, CheckCircle, AlertTriangle } from '../../../icons';
import api from '../../../utils/api';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { Save } from '../../../icons';
import type { FormMsg } from '../types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useState } from 'react';
import { Key, Trash2, UserPlus } from '../../../icons';
import type { FormMsg, UserEntry } from '../types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/** Wire + UI types for the Config page surface. */
export interface UserEntry {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { useCallback, useEffect, useMemo, useState } from 'react';
import api from '../../utils/api';
import type { ConfigData } from './types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { X, Lock, Copy, Check } from '../icons';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.credentials-root {
display: flex;
flex-direction: column;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useMemo, useRef, useState } from 'react';
import { useSearchParams, useNavigate } from 'react-router-dom';
import {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { ChevronRight as ChevR, Target } from '../../icons';
import EmptyState from '../EmptyState/EmptyState';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { ChevronRight as ChevR, Target } from '../../icons';
import EmptyState from '../EmptyState/EmptyState';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import type { SortDir } from './types';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { describe, it, expect } from 'vitest';
import {
nextSortState, reuseKey, sortCreds, sortReuse, truncHash,

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type { CredentialEntry, CredentialReuseRow, SortDir } from './types';
export const CREDS_LIMIT = 50;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export type { CredentialEntry } from '../CredentialsInspector';
export type { CredentialReuseRow } from '../CredentialReuseInspector';

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @vitest-environment jsdom
*/

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import { useCallback, useEffect, useState } from 'react';
import api from '../../utils/api';
import {

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React from 'react';
import { X, Lock, Copy, Send, Ban } from '../icons';
import { useToast } from './Toasts/useToast';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
.dashboard {
display: flex;
flex-direction: column;

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './Dashboard.css';

View File

@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
/* DeckyFleet — design-handoff port, scoped to the fleet view. */
.fleet-root { display: flex; flex-direction: column; gap: 24px; }

View File

@@ -1,3 +1,4 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { Server } from '../icons';
import { useToast } from './Toasts/useToast';

Some files were not shown because too many files have changed in this diff Show More