@ternent/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +17 -0
- package/.github/workflows/deploy-armour.yml +42 -0
- package/.github/workflows/deploy-identity.yml +42 -0
- package/.github/workflows/deploy-seal.yml +42 -0
- package/.github/workflows/deploy-ui.yml +42 -0
- package/.github/workflows/deploy-utils.yml +42 -0
- package/.github/workflows/release-create.yml +59 -0
- package/.github/workflows/release-publish.yml +54 -0
- package/.nvmrc +1 -0
- package/.ops/publish.mjs +31 -0
- package/package.json +16 -0
- package/packages/README.md +0 -0
- package/packages/armour/CHANGELOG.md +66 -0
- package/packages/armour/CLAUDE.md +8 -0
- package/packages/armour/README.md +103 -0
- package/packages/armour/SPEC.md +92 -0
- package/packages/armour/package.json +45 -0
- package/packages/armour/src/constants.ts +5 -0
- package/packages/armour/src/deps.d.ts +56 -0
- package/packages/armour/src/errors.ts +172 -0
- package/packages/armour/src/files.ts +73 -0
- package/packages/armour/src/identity.ts +72 -0
- package/packages/armour/src/index.ts +56 -0
- package/packages/armour/src/init.ts +10 -0
- package/packages/armour/src/passphrase.ts +33 -0
- package/packages/armour/src/recipients.ts +73 -0
- package/packages/armour/src/text.ts +68 -0
- package/packages/armour/src/types.ts +93 -0
- package/packages/armour/test/armour.test.ts +270 -0
- package/packages/armour/tsconfig.build.json +12 -0
- package/packages/armour/tsconfig.json +12 -0
- package/packages/armour/vite.config.ts +29 -0
- package/packages/concord/CHANGELOG.md +83 -0
- package/packages/concord/CLAUDE.md +9 -0
- package/packages/concord/README.md +146 -0
- package/packages/concord/SPEC.md +287 -0
- package/packages/concord/package.json +51 -0
- package/packages/concord/src/app.ts +717 -0
- package/packages/concord/src/errors.ts +9 -0
- package/packages/concord/src/index.ts +20 -0
- package/packages/concord/src/types.ts +127 -0
- package/packages/concord/test/concord.test.ts +978 -0
- package/packages/concord/tsconfig.json +12 -0
- package/packages/concord/vite.browser.config.ts +27 -0
- package/packages/concord/vite.config.ts +35 -0
- package/packages/concord/vite.config.ts.timestamp-1774262297922-ffd76e35ea668.mjs +83 -0
- package/packages/identity/CHANGELOG.md +47 -0
- package/packages/identity/README.md +236 -0
- package/packages/identity/package.json +41 -0
- package/packages/identity/src/index.ts +538 -0
- package/packages/identity/test/identity.test.ts +172 -0
- package/packages/identity/tsconfig.build.json +12 -0
- package/packages/identity/vite.config.ts +17 -0
- package/packages/ledger/CHANGELOG.md +69 -0
- package/packages/ledger/CLAUDE.md +9 -0
- package/packages/ledger/SPEC.md +304 -0
- package/packages/ledger/package.json +48 -0
- package/packages/ledger/src/index.ts +2 -0
- package/packages/ledger/src/ledger.ts +1286 -0
- package/packages/ledger/src/seal-cli.d.ts +25 -0
- package/packages/ledger/src/types.ts +294 -0
- package/packages/ledger/test/ledger.test.ts +838 -0
- package/packages/ledger/tsconfig.json +12 -0
- package/packages/ledger/vite.browser.config.ts +27 -0
- package/packages/ledger/vite.config.ts +39 -0
- package/packages/seal/CHANGELOG.md +137 -0
- package/packages/seal/CLAUDE.md +8 -0
- package/packages/seal/README.md +258 -0
- package/packages/seal/bin/seal +6 -0
- package/packages/seal/package.json +59 -0
- package/packages/seal/src/artifact.ts +380 -0
- package/packages/seal/src/cli.ts +372 -0
- package/packages/seal/src/commands/identity.ts +52 -0
- package/packages/seal/src/commands/manifest.ts +71 -0
- package/packages/seal/src/commands/publicKey.ts +7 -0
- package/packages/seal/src/commands/sign.ts +56 -0
- package/packages/seal/src/commands/verify.ts +54 -0
- package/packages/seal/src/crypto.ts +85 -0
- package/packages/seal/src/errors.ts +88 -0
- package/packages/seal/src/index.ts +5 -0
- package/packages/seal/src/manifest.ts +114 -0
- package/packages/seal/src/node.ts +18 -0
- package/packages/seal/src/proof.ts +344 -0
- package/packages/seal/test/artifact.test.ts +86 -0
- package/packages/seal/test/cli.test.ts +208 -0
- package/packages/seal/test/crypto.test.ts +21 -0
- package/packages/seal/test/manifest.test.ts +32 -0
- package/packages/seal/test/proof.test.ts +60 -0
- package/packages/seal/tsconfig.json +12 -0
- package/packages/seal/vite.config.ts +54 -0
- package/packages/ui/CHANGELOG.md +393 -0
- package/packages/ui/README.md +57 -0
- package/packages/ui/jsconfig.json +19 -0
- package/packages/ui/package.json +64 -0
- package/packages/ui/scripts/check-tokens.js +56 -0
- package/packages/ui/scripts/generate-theme-css.mjs +85 -0
- package/packages/ui/src/design-system/base.css +8 -0
- package/packages/ui/src/design-system/docs/ACCESSIBILITY_RULES.md +186 -0
- package/packages/ui/src/design-system/docs/AI_SYSTEM.md +281 -0
- package/packages/ui/src/design-system/docs/PATTERN_RULES.md +83 -0
- package/packages/ui/src/design-system/docs/PRIMITIVE_RULES.md +258 -0
- package/packages/ui/src/design-system/docs/TOKEN_RULES.md +235 -0
- package/packages/ui/src/design-system/docs/VISUAL_DIRECTION.md +68 -0
- package/packages/ui/src/design-system/foundation.js +420 -0
- package/packages/ui/src/design-system/tokens.css +140 -0
- package/packages/ui/src/design-system/tokens.js +327 -0
- package/packages/ui/src/design-system/utils.js +246 -0
- package/packages/ui/src/main.js +4 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.spec.md +24 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.types.ts +8 -0
- package/packages/ui/src/patterns/FeatureCard/FeatureCard.vue +175 -0
- package/packages/ui/src/patterns/FormField/FormField.spec.md +65 -0
- package/packages/ui/src/patterns/FormField/FormField.types.ts +11 -0
- package/packages/ui/src/patterns/FormField/FormField.vue +87 -0
- package/packages/ui/src/patterns/IdentityGlyph/IdentityGlyph.vue +61 -0
- package/packages/ui/src/patterns/IdentityGlyph/IdentityHandle.vue +58 -0
- package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.types.ts +36 -0
- package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.utils.ts +585 -0
- package/packages/ui/src/patterns/IdentityGlyph/index.ts +5 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.spec.md +28 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.types.ts +16 -0
- package/packages/ui/src/patterns/KeyValueList/KeyValueList.vue +50 -0
- package/packages/ui/src/patterns/LandingPage/LandingIcon.vue +90 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.spec.md +24 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.types.ts +212 -0
- package/packages/ui/src/patterns/LandingPage/LandingPage.vue +599 -0
- package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.test.ts +33 -0
- package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.vue +44 -0
- package/packages/ui/src/patterns/Logo/Logo.spec.md +22 -0
- package/packages/ui/src/patterns/Logo/Logo.vue +160 -0
- package/packages/ui/src/patterns/PageSurface/PageSurface.spec.md +15 -0
- package/packages/ui/src/patterns/PageSurface/PageSurface.vue +85 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.spec.md +39 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.types.ts +1 -0
- package/packages/ui/src/patterns/PanelChrome/PanelChrome.vue +187 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.spec.md +31 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.types.ts +23 -0
- package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.vue +354 -0
- package/packages/ui/src/patterns/RecordList/RecordList.spec.md +35 -0
- package/packages/ui/src/patterns/RecordList/RecordList.test.ts +42 -0
- package/packages/ui/src/patterns/RecordList/RecordList.types.ts +9 -0
- package/packages/ui/src/patterns/RecordList/RecordList.utils.ts +5 -0
- package/packages/ui/src/patterns/RecordList/RecordList.vue +134 -0
- package/packages/ui/src/patterns/SectionClarifier/SectionClarifier.vue +85 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.spec.md +25 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.types.ts +7 -0
- package/packages/ui/src/patterns/SectionIntro/SectionIntro.vue +141 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.spec.md +34 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.types.ts +17 -0
- package/packages/ui/src/patterns/SidebarNav/SidebarNav.vue +110 -0
- package/packages/ui/src/patterns/SplitView/SplitView.spec.md +28 -0
- package/packages/ui/src/patterns/SplitView/SplitView.test.ts +22 -0
- package/packages/ui/src/patterns/SplitView/SplitView.types.ts +3 -0
- package/packages/ui/src/patterns/SplitView/SplitView.utils.ts +13 -0
- package/packages/ui/src/patterns/SplitView/SplitView.vue +39 -0
- package/packages/ui/src/patterns/StepList/StepList.spec.md +15 -0
- package/packages/ui/src/patterns/StepList/StepList.types.ts +4 -0
- package/packages/ui/src/patterns/StepList/StepList.vue +91 -0
- package/packages/ui/src/patterns/Verification/VerificationBadge.vue +97 -0
- package/packages/ui/src/patterns/Verification/VerificationComponents.test.ts +153 -0
- package/packages/ui/src/patterns/Verification/VerificationDetailsPanel.vue +270 -0
- package/packages/ui/src/patterns/Verification/VerificationSummary.vue +171 -0
- package/packages/ui/src/patterns/Verification/index.ts +6 -0
- package/packages/ui/src/patterns/Verification/verification.types.ts +8 -0
- package/packages/ui/src/patterns/Verification/verification.utils.test.ts +37 -0
- package/packages/ui/src/patterns/Verification/verification.utils.ts +75 -0
- package/packages/ui/src/patterns/index.ts +25 -0
- package/packages/ui/src/primitives/Accordian/Accordian.vue +11 -0
- package/packages/ui/src/primitives/Accordian/AccordianItem.vue +14 -0
- package/packages/ui/src/primitives/Accordion/Accordion.props.ts +21 -0
- package/packages/ui/src/primitives/Accordion/Accordion.spec.md +50 -0
- package/packages/ui/src/primitives/Accordion/Accordion.types.ts +4 -0
- package/packages/ui/src/primitives/Accordion/Accordion.variants.ts +12 -0
- package/packages/ui/src/primitives/Accordion/Accordion.vue +71 -0
- package/packages/ui/src/primitives/Accordion/AccordionItem.props.ts +14 -0
- package/packages/ui/src/primitives/Accordion/AccordionItem.vue +40 -0
- package/packages/ui/src/primitives/Badge/Badge.props.ts +17 -0
- package/packages/ui/src/primitives/Badge/Badge.spec.md +17 -0
- package/packages/ui/src/primitives/Badge/Badge.types.ts +15 -0
- package/packages/ui/src/primitives/Badge/Badge.variants.ts +48 -0
- package/packages/ui/src/primitives/Badge/Badge.vue +31 -0
- package/packages/ui/src/primitives/Button/Button.props.ts +29 -0
- package/packages/ui/src/primitives/Button/Button.spec.md +139 -0
- package/packages/ui/src/primitives/Button/Button.types.ts +19 -0
- package/packages/ui/src/primitives/Button/Button.variants.ts +72 -0
- package/packages/ui/src/primitives/Button/Button.vue +90 -0
- package/packages/ui/src/primitives/Card/Card.props.ts +17 -0
- package/packages/ui/src/primitives/Card/Card.spec.md +29 -0
- package/packages/ui/src/primitives/Card/Card.types.ts +12 -0
- package/packages/ui/src/primitives/Card/Card.variants.ts +27 -0
- package/packages/ui/src/primitives/Card/Card.vue +37 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.props.ts +21 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.spec.md +51 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.types.ts +4 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.variants.ts +34 -0
- package/packages/ui/src/primitives/Checkbox/Checkbox.vue +92 -0
- package/packages/ui/src/primitives/Dialog/Dialog.props.ts +29 -0
- package/packages/ui/src/primitives/Dialog/Dialog.spec.md +52 -0
- package/packages/ui/src/primitives/Dialog/Dialog.types.ts +3 -0
- package/packages/ui/src/primitives/Dialog/Dialog.variants.ts +27 -0
- package/packages/ui/src/primitives/Dialog/Dialog.vue +78 -0
- package/packages/ui/src/primitives/Drawer/Drawer.props.ts +33 -0
- package/packages/ui/src/primitives/Drawer/Drawer.spec.md +50 -0
- package/packages/ui/src/primitives/Drawer/Drawer.types.ts +5 -0
- package/packages/ui/src/primitives/Drawer/Drawer.variants.ts +35 -0
- package/packages/ui/src/primitives/Drawer/Drawer.vue +88 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.props.ts +17 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.spec.md +35 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.types.ts +5 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.variants.ts +14 -0
- package/packages/ui/src/primitives/FieldMessage/FieldMessage.vue +40 -0
- package/packages/ui/src/primitives/FileInput/FileInput.props.ts +41 -0
- package/packages/ui/src/primitives/FileInput/FileInput.types.ts +6 -0
- package/packages/ui/src/primitives/FileInput/FileInput.variants.ts +46 -0
- package/packages/ui/src/primitives/FileInput/FileInput.vue +163 -0
- package/packages/ui/src/primitives/Input/Input.props.ts +29 -0
- package/packages/ui/src/primitives/Input/Input.spec.md +79 -0
- package/packages/ui/src/primitives/Input/Input.types.ts +13 -0
- package/packages/ui/src/primitives/Input/Input.variants.ts +54 -0
- package/packages/ui/src/primitives/Input/Input.vue +99 -0
- package/packages/ui/src/primitives/Label/Label.props.ts +25 -0
- package/packages/ui/src/primitives/Label/Label.spec.md +31 -0
- package/packages/ui/src/primitives/Label/Label.types.ts +3 -0
- package/packages/ui/src/primitives/Label/Label.variants.ts +17 -0
- package/packages/ui/src/primitives/Label/Label.vue +38 -0
- package/packages/ui/src/primitives/Menu/Menu.props.ts +17 -0
- package/packages/ui/src/primitives/Menu/Menu.spec.md +38 -0
- package/packages/ui/src/primitives/Menu/Menu.types.ts +10 -0
- package/packages/ui/src/primitives/Menu/Menu.variants.ts +10 -0
- package/packages/ui/src/primitives/Menu/Menu.vue +57 -0
- package/packages/ui/src/primitives/Popover/Popover.props.ts +25 -0
- package/packages/ui/src/primitives/Popover/Popover.spec.md +49 -0
- package/packages/ui/src/primitives/Popover/Popover.types.ts +3 -0
- package/packages/ui/src/primitives/Popover/Popover.variants.ts +18 -0
- package/packages/ui/src/primitives/Popover/Popover.vue +74 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.props.ts +29 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.spec.md +50 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.types.ts +12 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.variants.ts +48 -0
- package/packages/ui/src/primitives/RadioGroup/RadioGroup.vue +87 -0
- package/packages/ui/src/primitives/Separator/Separator.props.ts +9 -0
- package/packages/ui/src/primitives/Separator/Separator.spec.md +15 -0
- package/packages/ui/src/primitives/Separator/Separator.types.ts +3 -0
- package/packages/ui/src/primitives/Separator/Separator.variants.ts +8 -0
- package/packages/ui/src/primitives/Separator/Separator.vue +23 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.props.ts +21 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.spec.md +18 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.types.ts +5 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.variants.ts +18 -0
- package/packages/ui/src/primitives/Skeleton/Skeleton.vue +37 -0
- package/packages/ui/src/primitives/Spinner/Spinner.props.ts +13 -0
- package/packages/ui/src/primitives/Spinner/Spinner.spec.md +16 -0
- package/packages/ui/src/primitives/Spinner/Spinner.types.ts +5 -0
- package/packages/ui/src/primitives/Spinner/Spinner.variants.ts +15 -0
- package/packages/ui/src/primitives/Spinner/Spinner.vue +33 -0
- package/packages/ui/src/primitives/SplitButton/SplitButton.vue +108 -0
- package/packages/ui/src/primitives/Switch/Switch.props.ts +21 -0
- package/packages/ui/src/primitives/Switch/Switch.spec.md +49 -0
- package/packages/ui/src/primitives/Switch/Switch.types.ts +3 -0
- package/packages/ui/src/primitives/Switch/Switch.variants.ts +34 -0
- package/packages/ui/src/primitives/Switch/Switch.vue +71 -0
- package/packages/ui/src/primitives/Tabs/Tabs.props.ts +25 -0
- package/packages/ui/src/primitives/Tabs/Tabs.spec.md +48 -0
- package/packages/ui/src/primitives/Tabs/Tabs.types.ts +11 -0
- package/packages/ui/src/primitives/Tabs/Tabs.variants.ts +28 -0
- package/packages/ui/src/primitives/Tabs/Tabs.vue +59 -0
- package/packages/ui/src/primitives/Textarea/Textarea.props.ts +33 -0
- package/packages/ui/src/primitives/Textarea/Textarea.spec.md +59 -0
- package/packages/ui/src/primitives/Textarea/Textarea.types.ts +5 -0
- package/packages/ui/src/primitives/Textarea/Textarea.variants.ts +27 -0
- package/packages/ui/src/primitives/Textarea/Textarea.vue +74 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.props.ts +21 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.spec.md +45 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.types.ts +3 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.variants.ts +4 -0
- package/packages/ui/src/primitives/Tooltip/Tooltip.vue +31 -0
- package/packages/ui/src/primitives/TreeView/TreeView.types.ts +10 -0
- package/packages/ui/src/primitives/TreeView/TreeView.vue +113 -0
- package/packages/ui/src/primitives/TreeView/TreeViewNode.vue +190 -0
- package/packages/ui/src/primitives/index.ts +29 -0
- package/packages/ui/src/style.css +7 -0
- package/packages/ui/src/style.js +1 -0
- package/packages/ui/src/themes/armour.css +147 -0
- package/packages/ui/src/themes/aurora.css +147 -0
- package/packages/ui/src/themes/citrine-ash.css +147 -0
- package/packages/ui/src/themes/concord.css +147 -0
- package/packages/ui/src/themes/garnet-honey.css +147 -0
- package/packages/ui/src/themes/harbor-rose.css +147 -0
- package/packages/ui/src/themes/ledger.css +147 -0
- package/packages/ui/src/themes/neon-noir.css +74 -0
- package/packages/ui/src/themes/obsidian-iris.css +147 -0
- package/packages/ui/src/themes/pixpax.css +147 -0
- package/packages/ui/src/themes/print.css +147 -0
- package/packages/ui/src/themes/prism.css +147 -0
- package/packages/ui/src/themes/proof.css +145 -0
- package/packages/ui/src/themes/semanticThemeContract.js +2256 -0
- package/packages/ui/src/themes/spruce-ink.css +147 -0
- package/packages/ui/src/themes/sunset.css +147 -0
- package/packages/ui/tailwind.config.js +64 -0
- package/packages/ui/vite.config.js +35 -0
- package/packages/ui/vite.config.js.timestamp-1780697224943-89fbc929987bc.mjs +38 -0
- package/packages/utils/CHANGELOG.md +111 -0
- package/packages/utils/README.md +3 -0
- package/packages/utils/package.json +46 -0
- package/packages/utils/src/index.test.js +39 -0
- package/packages/utils/src/index.ts +289 -0
- package/packages/utils/tsconfig.build.json +12 -0
- package/packages/utils/vite.config.js +28 -0
- package/pnpm-workspace.yaml +8 -0
- package/scripts/vite/package-lib-config.ts +59 -0
- package/tsconfig.json +24 -0
- package/tsconfig.node.json +9 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { createIdentity, serializeIdentity } from "@ternent/identity";
|
|
6
|
+
import { recipientFromIdentity } from "@ternent/armour";
|
|
7
|
+
import { runCli } from "../src/cli";
|
|
8
|
+
|
|
9
|
+
async function createSigningEnv() {
|
|
10
|
+
const identity = await createIdentity();
|
|
11
|
+
return {
|
|
12
|
+
SEAL_IDENTITY: serializeIdentity(identity, false).trim(),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function createTempFile(name: string, content: string): Promise<string> {
|
|
17
|
+
const root = await mkdtemp(join(tmpdir(), "seal-cli-"));
|
|
18
|
+
const filePath = join(root, name);
|
|
19
|
+
await writeFile(filePath, content, "utf8");
|
|
20
|
+
return filePath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createWriter() {
|
|
24
|
+
let stdout = "";
|
|
25
|
+
let stderr = "";
|
|
26
|
+
return {
|
|
27
|
+
writer: {
|
|
28
|
+
stdout: (value: string) => {
|
|
29
|
+
stdout += value;
|
|
30
|
+
},
|
|
31
|
+
stderr: (value: string) => {
|
|
32
|
+
stderr += value;
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
read: () => ({ stdout, stderr }),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("seal cli", () => {
|
|
40
|
+
it("verifies a proof successfully", async () => {
|
|
41
|
+
const env = await createSigningEnv();
|
|
42
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
43
|
+
const proofPath = await createTempFile("proof.json", "");
|
|
44
|
+
const writer = createWriter();
|
|
45
|
+
|
|
46
|
+
const signExit = await runCli(["sign", "--input", subjectPath, "--out", proofPath], {
|
|
47
|
+
env,
|
|
48
|
+
writer: writer.writer,
|
|
49
|
+
});
|
|
50
|
+
const verifyExit = await runCli(
|
|
51
|
+
["verify", "--proof", proofPath, "--input", subjectPath, "--json"],
|
|
52
|
+
{ env, writer: writer.writer },
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(signExit).toBe(0);
|
|
56
|
+
expect(verifyExit).toBe(0);
|
|
57
|
+
expect(writer.read().stdout).toContain('"valid": true');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("signs and verifies an encrypted artifact successfully", async () => {
|
|
61
|
+
const env = await createSigningEnv();
|
|
62
|
+
const recipient = await createIdentity();
|
|
63
|
+
const recipientValue = await recipientFromIdentity(recipient);
|
|
64
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
65
|
+
const artifactPath = await createTempFile("artifact.json", "");
|
|
66
|
+
const writer = createWriter();
|
|
67
|
+
|
|
68
|
+
const signExit = await runCli(
|
|
69
|
+
["sign", "--input", subjectPath, "--recipient", recipientValue, "--out", artifactPath],
|
|
70
|
+
{ env, writer: writer.writer },
|
|
71
|
+
);
|
|
72
|
+
const verifyExit = await runCli(["verify", "--artifact", artifactPath, "--json"], {
|
|
73
|
+
writer: writer.writer,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(signExit).toBe(0);
|
|
77
|
+
expect(verifyExit).toBe(0);
|
|
78
|
+
expect(await readFile(artifactPath, "utf8")).toContain('"type": "seal-artifact"');
|
|
79
|
+
expect(writer.read().stdout).toContain('"encrypted": true');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("creates an identity file", async () => {
|
|
83
|
+
const identityPath = await createTempFile("identity.json", "");
|
|
84
|
+
const writer = createWriter();
|
|
85
|
+
|
|
86
|
+
const exitCode = await runCli(["identity", "create", "--out", identityPath, "--json"], {
|
|
87
|
+
writer: writer.writer,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
expect(exitCode).toBe(0);
|
|
91
|
+
expect(writer.read().stdout).toContain('"format": "ternent-identity"');
|
|
92
|
+
expect(await readFile(identityPath, "utf8")).toContain('"material"');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("creates a mnemonic-backed identity and writes the seed phrase", async () => {
|
|
96
|
+
const identityPath = await createTempFile("identity.json", "");
|
|
97
|
+
const mnemonicPath = await createTempFile("seed.txt", "");
|
|
98
|
+
const writer = createWriter();
|
|
99
|
+
|
|
100
|
+
const exitCode = await runCli(
|
|
101
|
+
[
|
|
102
|
+
"identity",
|
|
103
|
+
"create",
|
|
104
|
+
"--out",
|
|
105
|
+
identityPath,
|
|
106
|
+
"--words",
|
|
107
|
+
"24",
|
|
108
|
+
"--mnemonic-out",
|
|
109
|
+
mnemonicPath,
|
|
110
|
+
"--json",
|
|
111
|
+
],
|
|
112
|
+
{ writer: writer.writer },
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
expect(exitCode).toBe(0);
|
|
116
|
+
expect(writer.read().stdout).toContain('"mnemonic"');
|
|
117
|
+
expect(await readFile(identityPath, "utf8")).toContain('"format": "ternent-identity"');
|
|
118
|
+
expect(await readFile(mnemonicPath, "utf8")).toContain("Seal seed phrase backup");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("returns exit code 2 for a hash mismatch", async () => {
|
|
122
|
+
const env = await createSigningEnv();
|
|
123
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
124
|
+
const mismatchPath = await createTempFile("different.txt", "different\n");
|
|
125
|
+
const proofPath = await createTempFile("proof.json", "");
|
|
126
|
+
|
|
127
|
+
await runCli(["sign", "--input", subjectPath, "--out", proofPath], { env });
|
|
128
|
+
const exitCode = await runCli(["verify", "--proof", proofPath, "--input", mismatchPath], {
|
|
129
|
+
env,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(exitCode).toBe(2);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("keeps the legacy proof output when no recipients are provided", async () => {
|
|
136
|
+
const env = await createSigningEnv();
|
|
137
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
138
|
+
const proofPath = await createTempFile("proof.json", "");
|
|
139
|
+
|
|
140
|
+
const exitCode = await runCli(["sign", "--input", subjectPath, "--out", proofPath], { env });
|
|
141
|
+
|
|
142
|
+
expect(exitCode).toBe(0);
|
|
143
|
+
expect(await readFile(proofPath, "utf8")).toContain('"type": "seal-proof"');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("returns exit code 3 for an invalid signature", async () => {
|
|
147
|
+
const env = await createSigningEnv();
|
|
148
|
+
const otherEnv = await createSigningEnv();
|
|
149
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
150
|
+
const proofPath = await createTempFile("proof.json", "");
|
|
151
|
+
|
|
152
|
+
await runCli(["sign", "--input", subjectPath, "--out", proofPath], {
|
|
153
|
+
env: otherEnv,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const rawProof = await readFile(proofPath, "utf8");
|
|
157
|
+
const parsed = JSON.parse(rawProof) as Record<string, unknown>;
|
|
158
|
+
parsed.signer = {
|
|
159
|
+
...(parsed.signer as Record<string, unknown>),
|
|
160
|
+
keyId: "bad-key-id",
|
|
161
|
+
};
|
|
162
|
+
await writeFile(proofPath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
|
|
163
|
+
|
|
164
|
+
const exitCode = await runCli(["verify", "--proof", proofPath, "--input", subjectPath], {
|
|
165
|
+
env,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(exitCode).toBe(3);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("returns exit code 4 for schema invalid proof", async () => {
|
|
172
|
+
const env = await createSigningEnv();
|
|
173
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
174
|
+
const proofPath = await createTempFile("proof.json", '{"type":"bad"}');
|
|
175
|
+
|
|
176
|
+
const exitCode = await runCli(["verify", "--proof", proofPath, "--input", subjectPath], {
|
|
177
|
+
env,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(exitCode).toBe(4);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("returns exit code 5 for key mismatch", async () => {
|
|
184
|
+
const writer = createWriter();
|
|
185
|
+
|
|
186
|
+
const exitCode = await runCli(["public-key"], {
|
|
187
|
+
env: {},
|
|
188
|
+
writer: writer.writer,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
expect(exitCode).toBe(5);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("surfaces invalid recipients without leaking armour errors", async () => {
|
|
195
|
+
const env = await createSigningEnv();
|
|
196
|
+
const subjectPath = await createTempFile("sample.txt", "sample file\n");
|
|
197
|
+
const writer = createWriter();
|
|
198
|
+
|
|
199
|
+
const exitCode = await runCli(
|
|
200
|
+
["sign", "--input", subjectPath, "--recipient", "bad-recipient"],
|
|
201
|
+
{ env, writer: writer.writer },
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(exitCode).toBe(1);
|
|
205
|
+
expect(writer.read().stderr).toContain("Recipient must be a valid age recipient string.");
|
|
206
|
+
expect(writer.read().stderr).not.toContain("ARMOUR_");
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseIdentity } from "@ternent/identity";
|
|
3
|
+
import { createSealIdentity, createSealMnemonicIdentity, exportIdentityJson } from "../src";
|
|
4
|
+
|
|
5
|
+
describe("seal crypto", () => {
|
|
6
|
+
it("creates and serializes a seal identity", async () => {
|
|
7
|
+
const identity = await createSealIdentity("2026-03-17T00:00:00.000Z");
|
|
8
|
+
const exported = exportIdentityJson(identity);
|
|
9
|
+
|
|
10
|
+
expect(identity.format).toBe("ternent-identity");
|
|
11
|
+
expect(identity.version).toBe("2");
|
|
12
|
+
expect(parseIdentity(exported)).toEqual(identity);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("creates a mnemonic-backed seal identity", async () => {
|
|
16
|
+
const created = await createSealMnemonicIdentity({ words: 12 });
|
|
17
|
+
|
|
18
|
+
expect(created.mnemonic.split(/\s+/).length).toBe(12);
|
|
19
|
+
expect(created.identity.format).toBe("ternent-identity");
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { createManifestArtifact } from "../src/commands/manifest";
|
|
6
|
+
|
|
7
|
+
async function createFixtureTree(): Promise<string> {
|
|
8
|
+
const root = await mkdtemp(join(tmpdir(), "seal-manifest-"));
|
|
9
|
+
await mkdir(join(root, "nested"), { recursive: true });
|
|
10
|
+
await writeFile(join(root, "a.txt"), "alpha\n", "utf8");
|
|
11
|
+
await writeFile(join(root, ".DS_Store"), "ignore", "utf8");
|
|
12
|
+
await writeFile(join(root, "nested", "b.txt"), "beta\n", "utf8");
|
|
13
|
+
return root;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("manifest command", () => {
|
|
17
|
+
it("is deterministic across runs", async () => {
|
|
18
|
+
const fixtureRoot = await createFixtureTree();
|
|
19
|
+
const first = await createManifestArtifact(fixtureRoot);
|
|
20
|
+
const second = await createManifestArtifact(fixtureRoot);
|
|
21
|
+
|
|
22
|
+
expect(first.content).toBe(second.content);
|
|
23
|
+
expect(first.manifest).toEqual(second.manifest);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("excludes .DS_Store and sorts file keys", async () => {
|
|
27
|
+
const fixtureRoot = await createFixtureTree();
|
|
28
|
+
const { manifest } = await createManifestArtifact(fixtureRoot);
|
|
29
|
+
|
|
30
|
+
expect(Object.keys(manifest.files)).toEqual(["a.txt", "nested/b.txt"]);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createIdentity, deriveKeyId } from "@ternent/identity";
|
|
3
|
+
import {
|
|
4
|
+
createSealHash,
|
|
5
|
+
createSealProof,
|
|
6
|
+
createSealPublicKeyArtifact,
|
|
7
|
+
parseSealProofJson,
|
|
8
|
+
verifySealProofAgainstBytes,
|
|
9
|
+
verifySealProofSignature,
|
|
10
|
+
} from "../src/proof";
|
|
11
|
+
|
|
12
|
+
async function createSigner() {
|
|
13
|
+
const identity = await createIdentity();
|
|
14
|
+
return {
|
|
15
|
+
identity,
|
|
16
|
+
publicKey: identity.publicKey,
|
|
17
|
+
keyId: await deriveKeyId(identity.publicKey),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("seal proof", () => {
|
|
22
|
+
it("signs and verifies a valid proof", async () => {
|
|
23
|
+
const signer = await createSigner();
|
|
24
|
+
const bytes = new TextEncoder().encode("seal proof bytes");
|
|
25
|
+
const proof = await createSealProof({
|
|
26
|
+
signer: { identity: signer.identity },
|
|
27
|
+
subject: {
|
|
28
|
+
kind: "file",
|
|
29
|
+
path: "sample.txt",
|
|
30
|
+
hash: await createSealHash(bytes),
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const signatureCheck = await verifySealProofSignature(proof);
|
|
35
|
+
const verification = await verifySealProofAgainstBytes(proof, bytes);
|
|
36
|
+
|
|
37
|
+
expect(signatureCheck.ok).toBe(true);
|
|
38
|
+
expect(verification.valid).toBe(true);
|
|
39
|
+
expect(verification.keyId).toBe(signer.keyId);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("rejects invalid proof JSON", () => {
|
|
43
|
+
const parsed = parseSealProofJson("not-json");
|
|
44
|
+
|
|
45
|
+
expect(parsed.ok).toBe(false);
|
|
46
|
+
expect(parsed.errors[0]).toContain("not valid JSON");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("creates a portable public-key artifact", async () => {
|
|
50
|
+
const signer = await createSigner();
|
|
51
|
+
const artifact = await createSealPublicKeyArtifact({
|
|
52
|
+
identity: signer.identity,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
expect(artifact.publicKey).toBe(signer.publicKey);
|
|
56
|
+
expect(artifact.keyId).toBe(signer.keyId);
|
|
57
|
+
expect(artifact.version).toBe("2");
|
|
58
|
+
expect(artifact.type).toBe("seal-public-key");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Node",
|
|
7
|
+
"lib": ["ES2022", "DOM"],
|
|
8
|
+
"types": ["vitest/globals"]
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/**/*.ts", "test/**/*.ts", "vite.config.ts"],
|
|
11
|
+
"exclude": ["dist", "node_modules"]
|
|
12
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { defineConfig } from "vite";
|
|
4
|
+
import { createPackageExternal, resolvePackageDir } from "../../scripts/vite/package-lib-config";
|
|
5
|
+
|
|
6
|
+
const configDir = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const external = createPackageExternal(resolvePackageDir(import.meta.url), {
|
|
8
|
+
includeNodeBuiltins: true,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export default defineConfig(({ mode }) => {
|
|
12
|
+
const proofOnly = mode === "proof-only";
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
build: {
|
|
16
|
+
outDir: "dist",
|
|
17
|
+
target: "node20",
|
|
18
|
+
sourcemap: true,
|
|
19
|
+
minify: false,
|
|
20
|
+
rollupOptions: {
|
|
21
|
+
preserveEntrySignatures: "strict",
|
|
22
|
+
input: proofOnly
|
|
23
|
+
? {
|
|
24
|
+
proof: resolve(configDir, "src/proof.ts"),
|
|
25
|
+
crypto: resolve(configDir, "src/crypto.ts"),
|
|
26
|
+
}
|
|
27
|
+
: {
|
|
28
|
+
cli: resolve(configDir, "src/cli.ts"),
|
|
29
|
+
index: resolve(configDir, "src/index.ts"),
|
|
30
|
+
proof: resolve(configDir, "src/proof.ts"),
|
|
31
|
+
artifact: resolve(configDir, "src/artifact.ts"),
|
|
32
|
+
manifest: resolve(configDir, "src/manifest.ts"),
|
|
33
|
+
crypto: resolve(configDir, "src/crypto.ts"),
|
|
34
|
+
errors: resolve(configDir, "src/errors.ts"),
|
|
35
|
+
},
|
|
36
|
+
external,
|
|
37
|
+
output: {
|
|
38
|
+
format: "es",
|
|
39
|
+
entryFileNames: "[name].js",
|
|
40
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
test: {
|
|
45
|
+
environment: "node",
|
|
46
|
+
alias: {
|
|
47
|
+
"@ternent/armour": resolve(configDir, "../armour/src/index.ts"),
|
|
48
|
+
"@ternent/identity": resolve(configDir, "../identity-v2/src/index.ts"),
|
|
49
|
+
"@ternent/rage": resolve(configDir, "../rage/src/index.ts"),
|
|
50
|
+
"ternent-utils": resolve(configDir, "../utils/src/index.ts"),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
});
|