Validation (Angular)
The component can check a policy against ODRL profiles and show the findings. The service does the same without rendering. Both run the engine that the ds-prose-validate command runs, so the reports are the same.
A verdict of incomplete is never a pass: it means no error was found but something could not be checked, such as a declared profile that is not loaded.
Turning validation on #
strict turns it on with the default options. validation turns it on with options of your own and wins over strict. showViolations shows the findings under the prose, and has an effect only when validation is on.
Each row is evaluated against validationOptions in prose-angular/src/validation-sync.ts by a test, so this table is what the component does.
strict | validation | Options handed to the validator |
|---|---|---|
false | null | null |
true | null | {"strict":true} |
false | {"failClosed":true} | {"failClosed":true} |
true | {"strict":false} | {"strict":false} |
null in the last column means validation is off. The report signal is then null.
@Component({
selector: 'app-validated',
imports: [OdrlProseComponent],
template: `
<ds-odrl-prose [json]="policy" [profile]="profileText" [strict]="true" [showViolations]="true"
(validationChange)="onReport($event)" (validationError)="onError($event)" />
`,
})
export class ValidatedComponent {
policy = POLICY;
profileText = PROFILE_TEXT;
verdict = signal<ValidationReport['verdict'] | null>(null);
onReport(report: ValidationReport): void {
this.verdict.set(report.verdict);
}
onError(error: unknown): void {
console.error('validation options not readable', error);
}
}
From prose-angular/test/docs-examples.ts, region validation.
Profiles #
A profile is the text of an ODRL profile, JSON-LD, or Turtle with the Turtle build. The component does no network access. The profile input takes one text and profiles takes a list; a list wins, an empty list clears, and blank texts are dropped.
Each row is evaluated against profileTexts in the same file.
profile | profiles | Texts handed to the validator |
|---|---|---|
null | null | null |
"a" | null | ["a"] |
" " | null | null |
"a" | ["b"] | ["b"] |
"a" | [] | [] |
null | ["a", " ", "b"] | ["a","b"] |
profileLoaded emits a ProfileSummary for each profile read. profileError emits when a text cannot be read, and the previous profile stays. A profile or an options object that did not change is not handed to the wasm module again.
@Component({
selector: 'app-profiled',
imports: [OdrlProseComponent],
template: `
<ds-odrl-prose [json]="policy" [profile]="profileText"
(profileLoaded)="loaded($event)" (profileError)="failed($event)" />
`,
})
export class ProfiledComponent {
policy = POLICY;
profileText = PROFILE_TEXT;
loaded(summary: ProfileSummary): void {
console.log(summary.title, summary.terms);
}
failed(error: unknown): void {
console.error('profile not readable', error);
}
}
From prose-angular/test/docs-examples.ts, region profile.
Options #
validation takes ValidateOptions from @ds-labs/prose-wasm. Every field is optional, and {} is strict mode with the profile and prose rules.
| Field | Type | Meaning |
|---|---|---|
strict | boolean | Strict, the default, reads the vocabulary as closed. false is the advisory reading. |
structural | boolean | Also check the structural MUSTs of the Information Model (odrl.* rules). Off by default. |
failClosed | boolean | Make what could not be checked an error rather than a gap. |
denyDeprecated | boolean | Make a deprecated term an error rather than a warning. |
odrl | "common" | "core" | The ODRL terms defined without a profile: Core and Common (the default), or Core only. |
ruleset | number | Check only the rules of this ruleset and earlier, so a pinned check does not change with a release. |
rules | Partial<Record<RuleId, RuleLevel>> | A level per rule, over everything else. input.unreadable stays an error. |
@Component({
selector: 'app-options',
imports: [OdrlProseComponent],
template: `<ds-odrl-prose [json]="policy" [profile]="profileText" [validation]="options" [showViolations]="true" />`,
})
export class OptionsComponent {
policy = POLICY;
profileText = PROFILE_TEXT;
options: ValidateOptions = { strict: true, failClosed: true, denyDeprecated: true };
}
From prose-angular/test/docs-examples.ts, region options.
The report #
validationChange emits the report when its verdict or its set of findings changes. The first report counts. Wording and order do not count, so an edit that changes nothing the validator found is not an event. The report signal always holds the latest. validationError emits when the options cannot be read, and the previous options stay.
The report has schema ds-prose/validation-report@1. Its fields:
| Field | Type | Meaning |
|---|---|---|
schema | "ds-prose/validation-report@1" | The schema of the report. |
tool | { name: string; version: string } | The tool that wrote it. |
mode | "strict" | "advisory" | The reading used. |
tiers | string[] | The tiers of rules that ran. |
ruleset | number | The ruleset number. |
verdict | Verdict | "conforms", "violations" or "incomplete". |
vocabulary | { odrl: "common" | "core"; profiles: { iri: string | null; title: string | null; version: string | null }[] } | The vocabulary checked against. |
gaps | { rule: RuleId; detail: string }[] | What could not be checked. |
counts | { error: number; warning: number; info: number } | Findings by severity. |
findings | Finding[] | The findings. |
Each finding has a rule, a severity of "error", "warning" or "info", a message, a target, a fingerprint that stays the same when the input is reformatted, and fixes. The full type is Finding in @ds-labs/prose-wasm.
@Component({
selector: 'app-latest',
imports: [OdrlProseComponent],
template: `
<ds-odrl-prose #prose [json]="policy" [strict]="true" />
<p>{{ prose.report()?.verdict ?? 'validation is off' }}</p>
`,
})
export class LatestComponent {
policy = POLICY;
}
From prose-angular/test/docs-examples.ts, region report_signal.
Without rendering #
ProseValidatorService.validate(json, profiles, options) returns the report as a promise. It is strict unless options.strict is false. A problem in the policy is a finding, and a profile or options it cannot read is a rejection.
@Component({ selector: 'app-guard', template: '' })
export class GuardComponent {
private readonly validator = inject(ProseValidatorService);
async canSubmit(json: string, profileText: string): Promise<boolean> {
const report = await this.validator.validate(json, [profileText]);
return report.verdict === 'conforms';
}
}
From prose-angular/test/docs-examples.ts, region service.