Implement VEX document verification system with issuer management and signature verification
- Added IIssuerDirectory interface for managing VEX document issuers, including methods for registration, revocation, and trust validation. - Created InMemoryIssuerDirectory class as an in-memory implementation of IIssuerDirectory for testing and single-instance deployments. - Introduced ISignatureVerifier interface for verifying signatures on VEX documents, with support for multiple signature formats. - Developed SignatureVerifier class as the default implementation of ISignatureVerifier, allowing extensibility for different signature formats. - Implemented handlers for DSSE and JWS signature formats, including methods for verification and signature extraction. - Defined various records and enums for issuer and signature metadata, enhancing the structure and clarity of the verification process.
This commit is contained in:
@@ -2,11 +2,11 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
import type * as Monaco from 'monaco-editor';
|
||||
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker';
|
||||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker';
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker&inline';
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker&inline';
|
||||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker&inline';
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker&inline';
|
||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker&inline';
|
||||
|
||||
import {
|
||||
defineStellaDslTheme,
|
||||
|
||||
@@ -64,12 +64,11 @@ describe('PolicyEditorComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('loads pack content into the editor model', fakeAsync(() => {
|
||||
tick();
|
||||
it('loads pack content into the editor model', () => {
|
||||
expect(monacoLoader.model?.getValue()).toContain('package "demo"');
|
||||
}));
|
||||
});
|
||||
|
||||
it('applies lint diagnostics as Monaco markers', fakeAsync(() => {
|
||||
it('applies lint diagnostics as Monaco markers', () => {
|
||||
const lintResult = {
|
||||
valid: false,
|
||||
errors: [
|
||||
@@ -89,11 +88,10 @@ describe('PolicyEditorComponent', () => {
|
||||
policyApi.lint.and.returnValue(of(lintResult) as any);
|
||||
|
||||
component.triggerLint();
|
||||
tick();
|
||||
|
||||
expect(monacoLoader.lastMarkers.length).toBe(1);
|
||||
expect(monacoLoader.lastMarkers[0].message).toContain('Missing rule header');
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
class MonacoLoaderStub {
|
||||
@@ -102,34 +100,7 @@ class MonacoLoaderStub {
|
||||
lastMarkers: Monaco.editor.IMarkerData[] = [];
|
||||
|
||||
load = jasmine.createSpy('load').and.callFake(async () => {
|
||||
const self = this;
|
||||
return {
|
||||
editor: {
|
||||
createModel: (value: string) => {
|
||||
this.model = new FakeModel(value);
|
||||
this.editor = new FakeEditor(this.model);
|
||||
return this.model as unknown as Monaco.editor.ITextModel;
|
||||
},
|
||||
create: () => this.editor as unknown as Monaco.editor.IStandaloneCodeEditor,
|
||||
setModelMarkers: (
|
||||
_model: Monaco.editor.ITextModel,
|
||||
_owner: string,
|
||||
markers: Monaco.editor.IMarkerData[]
|
||||
) => {
|
||||
self.lastMarkers = markers;
|
||||
},
|
||||
},
|
||||
languages: {
|
||||
register: () => undefined,
|
||||
setMonarchTokensProvider: () => undefined,
|
||||
setLanguageConfiguration: () => undefined,
|
||||
},
|
||||
MarkerSeverity: {
|
||||
Error: 8,
|
||||
Warning: 4,
|
||||
Info: 2,
|
||||
},
|
||||
} as unknown as MonacoNamespace;
|
||||
return mockMonaco(this);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,3 +144,27 @@ class FakeEditor {
|
||||
}
|
||||
|
||||
type MonacoNamespace = typeof import('monaco-editor');
|
||||
|
||||
function mockMonaco(loader: MonacoLoaderStub): MonacoNamespace {
|
||||
const severity = { Error: 8, Warning: 4, Info: 2 };
|
||||
return {
|
||||
editor: {
|
||||
createModel: (value: string) => {
|
||||
loader.model = new FakeModel(value);
|
||||
loader.editor = new FakeEditor(loader.model);
|
||||
return loader.model as unknown as Monaco.editor.ITextModel;
|
||||
},
|
||||
create: () => loader.editor as unknown as Monaco.editor.IStandaloneCodeEditor,
|
||||
setModelMarkers: (_model: Monaco.editor.ITextModel, _owner: string, markers: Monaco.editor.IMarkerData[]) => {
|
||||
loader.lastMarkers = markers;
|
||||
},
|
||||
setTheme: () => undefined,
|
||||
},
|
||||
languages: {
|
||||
register: () => undefined,
|
||||
setMonarchTokensProvider: () => undefined,
|
||||
setLanguageConfiguration: () => undefined,
|
||||
},
|
||||
MarkerSeverity: severity as unknown as Monaco.editor.IMarkerSeverity,
|
||||
} as unknown as MonacoNamespace;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"failedTests": []
|
||||
{
|
||||
"status": "interrupted",
|
||||
"failedTests": []
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { policyAuthorSession } from '../src/app/testing';
|
||||
|
||||
const mockConfig = {
|
||||
authority: {
|
||||
@@ -24,7 +25,7 @@ const mockConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
page.on('console', (message) => {
|
||||
// bubble up browser logs for debugging
|
||||
console.log('[browser]', message.type(), message.text());
|
||||
@@ -32,7 +33,7 @@ test.beforeEach(async ({ page }) => {
|
||||
page.on('pageerror', (error) => {
|
||||
console.log('[pageerror]', error.message);
|
||||
});
|
||||
await page.addInitScript(() => {
|
||||
await page.addInitScript(() => {
|
||||
// Capture attempted redirects so the test can assert against them.
|
||||
(window as any).__stellaopsAssignedUrls = [];
|
||||
const originalAssign = window.location.assign.bind(window.location);
|
||||
@@ -40,8 +41,10 @@ test.beforeEach(async ({ page }) => {
|
||||
(window as any).__stellaopsAssignedUrls.push(url.toString());
|
||||
};
|
||||
|
||||
window.sessionStorage.clear();
|
||||
});
|
||||
window.sessionStorage.clear();
|
||||
// Seed a default Policy Studio author session so guarded routes load in e2e
|
||||
(window as any).__stellaopsTestSession = policyAuthorSession;
|
||||
});
|
||||
await page.route('**/config.json', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
|
||||
Reference in New Issue
Block a user