yarramate 0.21.0 → 0.23.0
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/catalogues/core-enrichment.yaml +402 -3
- package/dist/adapters/visual-graph-entry.d.ts +1 -0
- package/dist/adapters/visual-graph-entry.js +1 -0
- package/dist/compiler.d.ts +1 -19
- package/dist/compiler.js +43 -35
- package/dist/graph-claims.d.ts +18 -0
- package/dist/graph-claims.js +35 -0
- package/dist/graph-projection.d.ts +4 -3
- package/dist/graph-projection.js +1 -1
- package/dist/interrogate-command.d.ts +19 -0
- package/dist/interrogate-command.js +77 -16
- package/dist/notation/archimate.d.ts +71 -0
- package/dist/notation/archimate.js +183 -0
- package/dist/shipped-profile.d.ts +2 -0
- package/dist/shipped-profile.js +6 -0
- package/dist/visual-app/assets/index-CRd1Khma.js +354 -0
- package/dist/visual-app/index.html +1 -1
- package/docs/CONSUMING-YARRAMATE.md +26 -1
- package/package.json +10 -1
- package/profiles/yarramate-policy.yaml +18 -0
- package/schema/yarramate-question-catalogue.schema.json +132 -0
- package/schema/yarramate-visual-graph.schema.json +27 -2
- package/skills/yarramate-architecture/SKILL.md +18 -9
- package/skills/yarramate-architecture/references/native-authoring.md +10 -0
- package/dist/visual-app/assets/index-CAnZh3Hx.js +0 -354
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
format: yarramate/question-catalogue/v1
|
|
2
2
|
id: core-enrichment
|
|
3
|
-
version: "0.
|
|
3
|
+
version: "0.9"
|
|
4
4
|
profile: yarramate/core@0.1
|
|
5
5
|
presentation:
|
|
6
6
|
title: Core enrichment interview
|
|
7
7
|
description: >-
|
|
8
|
-
The guided design path: motivation, business, application,
|
|
9
|
-
and implementation waves plus cross-cutting hygiene. Each
|
|
8
|
+
The guided design path: motivation, interaction, business, application,
|
|
9
|
+
technology, and implementation waves plus cross-cutting hygiene. Each
|
|
10
|
+
question
|
|
10
11
|
states the decision its answer changes; a question that cannot is
|
|
11
12
|
deleted, not softened. Adequacy is enforced by linkage depth and
|
|
12
13
|
attestation, never by reading words. Versioning is additive within a
|
|
@@ -18,6 +19,12 @@ waves:
|
|
|
18
19
|
- id: motivation
|
|
19
20
|
name: Motivation
|
|
20
21
|
description: Why the system exists and what constrains it.
|
|
22
|
+
- id: interaction
|
|
23
|
+
name: Interaction
|
|
24
|
+
description: >-
|
|
25
|
+
Load-bearing hops: the behavior a component is assigned to, the
|
|
26
|
+
serving/triggering/flow mechanism, payload, trust, reliability, and
|
|
27
|
+
capacity. Hygiene waits.
|
|
21
28
|
- id: business
|
|
22
29
|
name: Business
|
|
23
30
|
description: Who acts, what is served, and what information matters.
|
|
@@ -333,6 +340,398 @@ questions:
|
|
|
333
340
|
attestation with topic "adequacy" (revoke by deleting it; Git
|
|
334
341
|
reviews both).
|
|
335
342
|
|
|
343
|
+
# ---- interaction ---------------------------------------------------------
|
|
344
|
+
- id: authn-standard-missing
|
|
345
|
+
wave: interaction
|
|
346
|
+
since: "0.9"
|
|
347
|
+
scope: workspace
|
|
348
|
+
trigger:
|
|
349
|
+
- condition: exists-linkage
|
|
350
|
+
kinds:
|
|
351
|
+
- yarramate/core@0.1#serving
|
|
352
|
+
- yarramate/core@0.1#flow
|
|
353
|
+
- yarramate/core@0.1#triggering
|
|
354
|
+
direction: either
|
|
355
|
+
counterpartKinds:
|
|
356
|
+
- yarramate/core@0.1#applicationComponent
|
|
357
|
+
- yarramate/core@0.1#applicationInterface
|
|
358
|
+
- yarramate/core@0.1#businessActor
|
|
359
|
+
- condition: no-subject-of-kind
|
|
360
|
+
kinds:
|
|
361
|
+
- yarramate/policy@0.1#authentication-constraint
|
|
362
|
+
question: >-
|
|
363
|
+
What is the default authentication mechanism for interactions in this
|
|
364
|
+
architecture?
|
|
365
|
+
askPlain: >-
|
|
366
|
+
When one system talks to another here, how do they prove who they
|
|
367
|
+
are? Pick the default now so each hop is not inventing its own.
|
|
368
|
+
materiality: >-
|
|
369
|
+
An unauthenticated hop to another system is a trust-boundary decision
|
|
370
|
+
nobody recorded. Implementers will pick a mechanism in code, and the
|
|
371
|
+
next hop will assume a different one. This question does not cover
|
|
372
|
+
authorization or transport security.
|
|
373
|
+
authority: human
|
|
374
|
+
resolution: >-
|
|
375
|
+
Add an authentication-constraint (the standard, or a not-applicable
|
|
376
|
+
subject with the reason in its description) in a document that
|
|
377
|
+
selects yarramate/policy@0.1.
|
|
378
|
+
|
|
379
|
+
- id: ratelimit-standard-missing
|
|
380
|
+
wave: interaction
|
|
381
|
+
since: "0.9"
|
|
382
|
+
scope: workspace
|
|
383
|
+
trigger:
|
|
384
|
+
- condition: exists-linkage
|
|
385
|
+
kinds:
|
|
386
|
+
- yarramate/core@0.1#serving
|
|
387
|
+
direction: either
|
|
388
|
+
counterpartKinds:
|
|
389
|
+
- yarramate/core@0.1#businessActor
|
|
390
|
+
- condition: no-subject-of-kind
|
|
391
|
+
kinds:
|
|
392
|
+
- yarramate/policy@0.1#rate-limit-constraint
|
|
393
|
+
question: >-
|
|
394
|
+
Where is rate limiting a requirement, and what is the default rule?
|
|
395
|
+
askPlain: >-
|
|
396
|
+
Do caller-facing APIs have a capacity cap? If yes, what is it? If
|
|
397
|
+
no, say so so we do not keep asking per hop.
|
|
398
|
+
materiality: >-
|
|
399
|
+
Caller-facing hops without a capacity rule are sized by whoever
|
|
400
|
+
implements first. An explicit none is a decision; silence is not.
|
|
401
|
+
authority: human
|
|
402
|
+
resolution: >-
|
|
403
|
+
Add a rate-limit-constraint for the default cap, or a
|
|
404
|
+
ratelimit-not-applicable subject. Bind hop-specific values with
|
|
405
|
+
expects on the binding.
|
|
406
|
+
|
|
407
|
+
- id: reliability-standard-missing
|
|
408
|
+
wave: interaction
|
|
409
|
+
since: "0.9"
|
|
410
|
+
scope: workspace
|
|
411
|
+
trigger:
|
|
412
|
+
- condition: exists-linkage
|
|
413
|
+
kinds:
|
|
414
|
+
- yarramate/core@0.1#flow
|
|
415
|
+
- yarramate/core@0.1#triggering
|
|
416
|
+
direction: either
|
|
417
|
+
counterpartKinds:
|
|
418
|
+
- yarramate/core@0.1#applicationComponent
|
|
419
|
+
- yarramate/core@0.1#applicationInterface
|
|
420
|
+
- yarramate/core@0.1#applicationProcess
|
|
421
|
+
- yarramate/core@0.1#applicationFunction
|
|
422
|
+
- yarramate/core@0.1#applicationInteraction
|
|
423
|
+
- yarramate/core@0.1#applicationEvent
|
|
424
|
+
- yarramate/core@0.1#businessActor
|
|
425
|
+
- condition: no-subject-of-kind
|
|
426
|
+
kinds:
|
|
427
|
+
- yarramate/policy@0.1#reliability-constraint
|
|
428
|
+
question: >-
|
|
429
|
+
What is the default delivery, retry, and idempotency rule for
|
|
430
|
+
asynchronous or content-moving interactions?
|
|
431
|
+
askPlain: >-
|
|
432
|
+
When a message or payload does not arrive, do we retry, and what
|
|
433
|
+
makes a retry safe to repeat?
|
|
434
|
+
materiality: >-
|
|
435
|
+
Retry without idempotency duplicates work; no retry without a
|
|
436
|
+
recorded choice leaves timeout behaviour to each implementer.
|
|
437
|
+
authority: human
|
|
438
|
+
resolution: >-
|
|
439
|
+
Add a reliability-constraint (the standard, or not-applicable with
|
|
440
|
+
the reason in its description).
|
|
441
|
+
|
|
442
|
+
- id: hop-unrealised
|
|
443
|
+
wave: interaction
|
|
444
|
+
since: "0.9"
|
|
445
|
+
scope: subject
|
|
446
|
+
subjects:
|
|
447
|
+
kinds:
|
|
448
|
+
- yarramate/core@0.1#applicationComponent
|
|
449
|
+
statuses:
|
|
450
|
+
- planned
|
|
451
|
+
- current
|
|
452
|
+
trigger:
|
|
453
|
+
- condition: has-linkage
|
|
454
|
+
kinds:
|
|
455
|
+
- yarramate/core@0.1#serving
|
|
456
|
+
- yarramate/core@0.1#flow
|
|
457
|
+
- yarramate/core@0.1#triggering
|
|
458
|
+
direction: either
|
|
459
|
+
counterpartKinds:
|
|
460
|
+
- yarramate/core@0.1#applicationComponent
|
|
461
|
+
- yarramate/core@0.1#applicationInterface
|
|
462
|
+
- yarramate/core@0.1#businessActor
|
|
463
|
+
- condition: missing-linkage
|
|
464
|
+
kinds:
|
|
465
|
+
- yarramate/core@0.1#assignment
|
|
466
|
+
direction: outgoing
|
|
467
|
+
counterpartKinds:
|
|
468
|
+
- yarramate/core@0.1#applicationProcess
|
|
469
|
+
- yarramate/core@0.1#applicationFunction
|
|
470
|
+
- yarramate/core@0.1#applicationInteraction
|
|
471
|
+
- yarramate/core@0.1#applicationEvent
|
|
472
|
+
- yarramate/core@0.1#applicationInterface
|
|
473
|
+
question: >-
|
|
474
|
+
{subject.name} participates in an application interaction, but
|
|
475
|
+
nothing it is assigned to is that interaction. What process,
|
|
476
|
+
function, interaction, event, or interface is the hop?
|
|
477
|
+
askPlain: >-
|
|
478
|
+
{subject.name} talks to something else, but the model never names
|
|
479
|
+
the work it does in that talk. What is the actual step?
|
|
480
|
+
materiality: >-
|
|
481
|
+
A component-to-component edge with no assigned behavior is
|
|
482
|
+
inventory. Protocol, trust, payload, and failure have nowhere to
|
|
483
|
+
bind until the hop is a subject.
|
|
484
|
+
authority: either
|
|
485
|
+
resolution: >-
|
|
486
|
+
Add an application process, function, interaction, event, or
|
|
487
|
+
interface, assign this component to it, and relate that behavior
|
|
488
|
+
with serving, triggering, or flow to its counterpart. Do not answer
|
|
489
|
+
by deleting the component or adding a realization instead.
|
|
490
|
+
|
|
491
|
+
- id: interaction-protocol-unbound
|
|
492
|
+
wave: interaction
|
|
493
|
+
since: "0.9"
|
|
494
|
+
scope: subject
|
|
495
|
+
subjects:
|
|
496
|
+
kinds:
|
|
497
|
+
- yarramate/core@0.1#applicationProcess
|
|
498
|
+
- yarramate/core@0.1#applicationFunction
|
|
499
|
+
- yarramate/core@0.1#applicationInteraction
|
|
500
|
+
- yarramate/core@0.1#applicationEvent
|
|
501
|
+
- yarramate/core@0.1#applicationInterface
|
|
502
|
+
statuses:
|
|
503
|
+
- planned
|
|
504
|
+
- current
|
|
505
|
+
trigger:
|
|
506
|
+
- condition: has-linkage
|
|
507
|
+
kinds:
|
|
508
|
+
- yarramate/core@0.1#serving
|
|
509
|
+
direction: either
|
|
510
|
+
counterpartKinds:
|
|
511
|
+
- yarramate/core@0.1#applicationComponent
|
|
512
|
+
- yarramate/core@0.1#applicationInterface
|
|
513
|
+
- yarramate/core@0.1#applicationProcess
|
|
514
|
+
- yarramate/core@0.1#applicationFunction
|
|
515
|
+
- yarramate/core@0.1#applicationInteraction
|
|
516
|
+
- yarramate/core@0.1#applicationEvent
|
|
517
|
+
- yarramate/core@0.1#businessActor
|
|
518
|
+
- condition: missing-constraint
|
|
519
|
+
kinds:
|
|
520
|
+
- yarramate/policy@0.1#mechanism-constraint
|
|
521
|
+
question: >-
|
|
522
|
+
{subject.name} is a serving hop. Which protocol is it — REST/HTTP,
|
|
523
|
+
SOAP, GraphQL, or something else?
|
|
524
|
+
askPlain: >-
|
|
525
|
+
When {subject.name} is called, what is the wire protocol?
|
|
526
|
+
materiality: >-
|
|
527
|
+
Serving names the pattern, not the contract. A REST hop and a SOAP
|
|
528
|
+
hop fail, version, and authenticate differently.
|
|
529
|
+
authority: either
|
|
530
|
+
resolution: >-
|
|
531
|
+
Bind a mechanism-constraint on this behavior (or a not-applicable
|
|
532
|
+
subject if the serving kind is already the whole answer).
|
|
533
|
+
|
|
534
|
+
- id: interaction-content-unknown
|
|
535
|
+
wave: interaction
|
|
536
|
+
since: "0.9"
|
|
537
|
+
scope: subject
|
|
538
|
+
subjects:
|
|
539
|
+
kinds:
|
|
540
|
+
- yarramate/core@0.1#applicationProcess
|
|
541
|
+
- yarramate/core@0.1#applicationFunction
|
|
542
|
+
- yarramate/core@0.1#applicationInteraction
|
|
543
|
+
- yarramate/core@0.1#applicationEvent
|
|
544
|
+
- yarramate/core@0.1#applicationInterface
|
|
545
|
+
statuses:
|
|
546
|
+
- planned
|
|
547
|
+
- current
|
|
548
|
+
trigger:
|
|
549
|
+
- condition: missing-flow-content
|
|
550
|
+
question: >-
|
|
551
|
+
{subject.name} sends a flow with no content. What moves?
|
|
552
|
+
askPlain: >-
|
|
553
|
+
{subject.name} sends something on. What is that something called?
|
|
554
|
+
materiality: >-
|
|
555
|
+
A flow with no content is an unnamed payload. Retry, scanning, and
|
|
556
|
+
the counterpart contract have nothing to name.
|
|
557
|
+
authority: either
|
|
558
|
+
resolution: >-
|
|
559
|
+
Set content on the flow relationship.
|
|
560
|
+
|
|
561
|
+
- id: interaction-contract-unknown
|
|
562
|
+
wave: interaction
|
|
563
|
+
since: "0.9"
|
|
564
|
+
scope: subject
|
|
565
|
+
subjects:
|
|
566
|
+
kinds:
|
|
567
|
+
- yarramate/core@0.1#applicationProcess
|
|
568
|
+
- yarramate/core@0.1#applicationFunction
|
|
569
|
+
- yarramate/core@0.1#applicationInteraction
|
|
570
|
+
- yarramate/core@0.1#applicationEvent
|
|
571
|
+
- yarramate/core@0.1#applicationInterface
|
|
572
|
+
statuses:
|
|
573
|
+
- planned
|
|
574
|
+
- current
|
|
575
|
+
trigger:
|
|
576
|
+
- condition: has-linkage
|
|
577
|
+
kinds:
|
|
578
|
+
- yarramate/core@0.1#serving
|
|
579
|
+
- yarramate/core@0.1#flow
|
|
580
|
+
- yarramate/core@0.1#triggering
|
|
581
|
+
direction: either
|
|
582
|
+
counterpartKinds:
|
|
583
|
+
- yarramate/core@0.1#applicationComponent
|
|
584
|
+
- yarramate/core@0.1#applicationInterface
|
|
585
|
+
- yarramate/core@0.1#applicationProcess
|
|
586
|
+
- yarramate/core@0.1#applicationFunction
|
|
587
|
+
- yarramate/core@0.1#applicationInteraction
|
|
588
|
+
- yarramate/core@0.1#applicationEvent
|
|
589
|
+
- yarramate/core@0.1#businessActor
|
|
590
|
+
- condition: missing-linkage
|
|
591
|
+
kinds:
|
|
592
|
+
- yarramate/core@0.1#access
|
|
593
|
+
direction: outgoing
|
|
594
|
+
counterpartKinds:
|
|
595
|
+
- yarramate/core@0.1#dataObject
|
|
596
|
+
- yarramate/core@0.1#contract
|
|
597
|
+
question: >-
|
|
598
|
+
{subject.name} participates in a hop but accesses no contract or
|
|
599
|
+
data object. What information does it read or write?
|
|
600
|
+
askPlain: >-
|
|
601
|
+
What record or contract is {subject.name} working with?
|
|
602
|
+
materiality: >-
|
|
603
|
+
Schema ownership, identifiers, and classification have nowhere to
|
|
604
|
+
attach until the hop names the information it moves.
|
|
605
|
+
authority: either
|
|
606
|
+
resolution: >-
|
|
607
|
+
Add access from this behavior to a dataObject or contract.
|
|
608
|
+
|
|
609
|
+
- id: interaction-trust-unbound
|
|
610
|
+
wave: interaction
|
|
611
|
+
since: "0.9"
|
|
612
|
+
scope: subject
|
|
613
|
+
subjects:
|
|
614
|
+
kinds:
|
|
615
|
+
- yarramate/core@0.1#applicationProcess
|
|
616
|
+
- yarramate/core@0.1#applicationFunction
|
|
617
|
+
- yarramate/core@0.1#applicationInteraction
|
|
618
|
+
- yarramate/core@0.1#applicationEvent
|
|
619
|
+
- yarramate/core@0.1#applicationInterface
|
|
620
|
+
statuses:
|
|
621
|
+
- planned
|
|
622
|
+
- current
|
|
623
|
+
trigger:
|
|
624
|
+
- condition: has-linkage
|
|
625
|
+
kinds:
|
|
626
|
+
- yarramate/core@0.1#serving
|
|
627
|
+
- yarramate/core@0.1#flow
|
|
628
|
+
- yarramate/core@0.1#triggering
|
|
629
|
+
direction: either
|
|
630
|
+
counterpartKinds:
|
|
631
|
+
- yarramate/core@0.1#applicationComponent
|
|
632
|
+
- yarramate/core@0.1#applicationInterface
|
|
633
|
+
- yarramate/core@0.1#applicationProcess
|
|
634
|
+
- yarramate/core@0.1#applicationFunction
|
|
635
|
+
- yarramate/core@0.1#applicationInteraction
|
|
636
|
+
- yarramate/core@0.1#applicationEvent
|
|
637
|
+
- yarramate/core@0.1#businessActor
|
|
638
|
+
- condition: missing-constraint
|
|
639
|
+
kinds:
|
|
640
|
+
- yarramate/policy@0.1#authentication-constraint
|
|
641
|
+
question: >-
|
|
642
|
+
How is trust established for {subject.name}?
|
|
643
|
+
askPlain: >-
|
|
644
|
+
Who does {subject.name} authenticate as, and with what?
|
|
645
|
+
materiality: >-
|
|
646
|
+
An unauthenticated hop to another system is a trust-boundary
|
|
647
|
+
decision nobody recorded. This is authentication only — not
|
|
648
|
+
authorization or transport security.
|
|
649
|
+
authority: either
|
|
650
|
+
resolution: >-
|
|
651
|
+
Bind an authentication-constraint on this behavior, or a
|
|
652
|
+
not-applicable subject if this hop is deliberately unauthenticated.
|
|
653
|
+
|
|
654
|
+
- id: interaction-reliability-unbound
|
|
655
|
+
wave: interaction
|
|
656
|
+
since: "0.9"
|
|
657
|
+
scope: subject
|
|
658
|
+
subjects:
|
|
659
|
+
kinds:
|
|
660
|
+
- yarramate/core@0.1#applicationProcess
|
|
661
|
+
- yarramate/core@0.1#applicationFunction
|
|
662
|
+
- yarramate/core@0.1#applicationInteraction
|
|
663
|
+
- yarramate/core@0.1#applicationEvent
|
|
664
|
+
- yarramate/core@0.1#applicationInterface
|
|
665
|
+
statuses:
|
|
666
|
+
- planned
|
|
667
|
+
- current
|
|
668
|
+
trigger:
|
|
669
|
+
- condition: has-linkage
|
|
670
|
+
kinds:
|
|
671
|
+
- yarramate/core@0.1#triggering
|
|
672
|
+
- yarramate/core@0.1#flow
|
|
673
|
+
direction: either
|
|
674
|
+
counterpartKinds:
|
|
675
|
+
- yarramate/core@0.1#applicationComponent
|
|
676
|
+
- yarramate/core@0.1#applicationInterface
|
|
677
|
+
- yarramate/core@0.1#applicationProcess
|
|
678
|
+
- yarramate/core@0.1#applicationFunction
|
|
679
|
+
- yarramate/core@0.1#applicationInteraction
|
|
680
|
+
- yarramate/core@0.1#applicationEvent
|
|
681
|
+
- yarramate/core@0.1#businessActor
|
|
682
|
+
- condition: missing-constraint
|
|
683
|
+
kinds:
|
|
684
|
+
- yarramate/policy@0.1#reliability-constraint
|
|
685
|
+
question: >-
|
|
686
|
+
What happens when {subject.name} fails — retry, idempotency,
|
|
687
|
+
dead-letter, compensation?
|
|
688
|
+
askPlain: >-
|
|
689
|
+
If {subject.name} does not finish, do we retry, and what makes a
|
|
690
|
+
retry safe?
|
|
691
|
+
materiality: >-
|
|
692
|
+
A content-moving hop without a reliability rule duplicates or
|
|
693
|
+
drops work at the first timeout.
|
|
694
|
+
authority: either
|
|
695
|
+
resolution: >-
|
|
696
|
+
Bind a reliability-constraint. A named failure process is stronger
|
|
697
|
+
and may come later; the constraint is the 0.9 closer.
|
|
698
|
+
|
|
699
|
+
- id: interaction-capacity-unbound
|
|
700
|
+
wave: interaction
|
|
701
|
+
since: "0.9"
|
|
702
|
+
scope: subject
|
|
703
|
+
subjects:
|
|
704
|
+
kinds:
|
|
705
|
+
- yarramate/core@0.1#applicationProcess
|
|
706
|
+
- yarramate/core@0.1#applicationFunction
|
|
707
|
+
- yarramate/core@0.1#applicationInteraction
|
|
708
|
+
- yarramate/core@0.1#applicationEvent
|
|
709
|
+
- yarramate/core@0.1#applicationInterface
|
|
710
|
+
statuses:
|
|
711
|
+
- planned
|
|
712
|
+
- current
|
|
713
|
+
trigger:
|
|
714
|
+
- condition: has-linkage
|
|
715
|
+
kinds:
|
|
716
|
+
- yarramate/core@0.1#serving
|
|
717
|
+
direction: either
|
|
718
|
+
counterpartKinds:
|
|
719
|
+
- yarramate/core@0.1#businessActor
|
|
720
|
+
- condition: missing-constraint
|
|
721
|
+
kinds:
|
|
722
|
+
- yarramate/policy@0.1#rate-limit-constraint
|
|
723
|
+
question: >-
|
|
724
|
+
What is the capacity rule for {subject.name}?
|
|
725
|
+
askPlain: >-
|
|
726
|
+
How hard may callers hit {subject.name}, or is there no cap?
|
|
727
|
+
materiality: >-
|
|
728
|
+
An Experience-facing hop without a capacity rule is sized by
|
|
729
|
+
whoever implements first. Explicit none is a decision.
|
|
730
|
+
authority: either
|
|
731
|
+
resolution: >-
|
|
732
|
+
Bind a rate-limit-constraint, with expects on the binding for the
|
|
733
|
+
numeric cap, or a not-applicable subject.
|
|
734
|
+
|
|
336
735
|
# ---- business ------------------------------------------------------------
|
|
337
736
|
- id: service-consumer-unknown
|
|
338
737
|
wave: business
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { projectGraphForCanvas, type CanvasGraph, type CanvasNode, type CanvasEdge, } from '../graph-projection.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { projectGraphForCanvas, } from '../graph-projection.js';
|
package/dist/compiler.d.ts
CHANGED
|
@@ -108,24 +108,7 @@ export type IncrementalCompilationResult = ({
|
|
|
108
108
|
readonly incremental: boolean;
|
|
109
109
|
readonly cache: CompilationCache;
|
|
110
110
|
};
|
|
111
|
-
export
|
|
112
|
-
export declare const attestationClaimValue: (attestation: {
|
|
113
|
-
readonly by: string;
|
|
114
|
-
readonly on: string;
|
|
115
|
-
readonly recordedBy?: string;
|
|
116
|
-
}) => string;
|
|
117
|
-
export interface AttestationClaimParts {
|
|
118
|
-
readonly by: string;
|
|
119
|
-
readonly on: string;
|
|
120
|
-
readonly recordedBy?: string;
|
|
121
|
-
}
|
|
122
|
-
export declare const parseAttestationClaimValue: (value: string) => AttestationClaimParts | undefined;
|
|
123
|
-
export interface ConstraintExpectsParts {
|
|
124
|
-
readonly provider: string;
|
|
125
|
-
readonly key: string;
|
|
126
|
-
readonly value: string;
|
|
127
|
-
}
|
|
128
|
-
export declare const parseConstraintExpectsValue: (value: string) => ConstraintExpectsParts | undefined;
|
|
111
|
+
export { ATTESTATION_PREDICATE_PREFIX, attestationClaimValue, parseAttestationClaimValue, parseConstraintExpectsValue, type AttestationClaimParts, type ConstraintExpectsParts, } from './graph-claims.js';
|
|
129
112
|
interface ResolvedPosition {
|
|
130
113
|
readonly line: number;
|
|
131
114
|
readonly col: number;
|
|
@@ -142,4 +125,3 @@ export declare const compileWorkspaceWithProfileContext: (sources: readonly Work
|
|
|
142
125
|
* composed value per current source and drops sources that left the workspace.
|
|
143
126
|
*/
|
|
144
127
|
export declare const compileWorkspaceIncremental: (sources: readonly WorkspaceSource[], previous?: CompilationCache) => IncrementalCompilationResult;
|
|
145
|
-
export {};
|
package/dist/compiler.js
CHANGED
|
@@ -6,6 +6,8 @@ import documentSchema from '../schema/yarramate-document.schema.json' with { typ
|
|
|
6
6
|
};
|
|
7
7
|
import profileSchema from '../schema/yarramate-profile.schema.json' with { type: 'json'
|
|
8
8
|
};
|
|
9
|
+
import { ATTESTATION_PREDICATE_PREFIX, attestationClaimValue } from './graph-claims.js';
|
|
10
|
+
import { shippedPolicyIdentity, shippedPolicySource, } from './shipped-profile.js';
|
|
9
11
|
const coreProfile = 'yarramate/core@0.1';
|
|
10
12
|
const require = createRequire(import.meta.url);
|
|
11
13
|
const ajv2020Module = require('ajv/dist/2020.js');
|
|
@@ -39,41 +41,7 @@ const presenceClaimId = (subject, state) => `${subject}~present-in-${Buffer.from
|
|
|
39
41
|
const aliasClaimId = (subject, alias) => `${subject}~alias-${Buffer.from(alias, 'utf8').toString('hex')}`;
|
|
40
42
|
const distinctFromClaimId = (subject, other) => `${subject}~distinct-from-${Buffer.from(other, 'utf8').toString('hex')}`;
|
|
41
43
|
const supersedesClaimId = (subject, predecessor) => `${subject}~supersedes-${Buffer.from(predecessor, 'utf8').toString('hex')}`;
|
|
42
|
-
export
|
|
43
|
-
// An attestation claim packs the authority, the date it was given, and
|
|
44
|
-
// the recorder when a machine held the pen. A reference carries no
|
|
45
|
-
// spaces and the date is fixed width, so the three parse back out of one
|
|
46
|
-
// value unambiguously wherever a reader needs them.
|
|
47
|
-
export const attestationClaimValue = (attestation) => attestation.recordedBy === undefined
|
|
48
|
-
? `${attestation.by} ${attestation.on}`
|
|
49
|
-
: `${attestation.by} ${attestation.on} ${attestation.recordedBy}`;
|
|
50
|
-
export const parseAttestationClaimValue = (value) => {
|
|
51
|
-
const match = /^(\S+) ([0-9]{4}-[0-9]{2}-[0-9]{2})(?: (.+))?$/.exec(value);
|
|
52
|
-
if (match === null)
|
|
53
|
-
return undefined;
|
|
54
|
-
const recordedBy = match[3];
|
|
55
|
-
return {
|
|
56
|
-
by: match[1],
|
|
57
|
-
on: match[2],
|
|
58
|
-
...(recordedBy === undefined ? {} : { recordedBy }),
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
// Mirrors the compiler's own write-side encoding (ADR 0075): provider and
|
|
62
|
-
// key admit no whitespace, so the first two spaces delimit them and
|
|
63
|
-
// everything after the second space is the expected value verbatim, spaces
|
|
64
|
-
// included. This is the sole authority for decoding the value written at
|
|
65
|
-
// the constraint's `expects` claim — reconciliation.ts delegates here
|
|
66
|
-
// rather than mirroring the regex itself.
|
|
67
|
-
export const parseConstraintExpectsValue = (value) => {
|
|
68
|
-
const match = /^(\S+) (\S+) ([\s\S]+)$/.exec(value);
|
|
69
|
-
if (match === null)
|
|
70
|
-
return undefined;
|
|
71
|
-
return {
|
|
72
|
-
provider: match[1],
|
|
73
|
-
key: match[2],
|
|
74
|
-
value: match[3],
|
|
75
|
-
};
|
|
76
|
-
};
|
|
44
|
+
export { ATTESTATION_PREDICATE_PREFIX, attestationClaimValue, parseAttestationClaimValue, parseConstraintExpectsValue, } from './graph-claims.js';
|
|
77
45
|
const describeAspect = (aspect) => aspect.replace('-', ' ');
|
|
78
46
|
// Candidate order is the policy-matrix declaration order: the resolved kind
|
|
79
47
|
// map inserts core policies first, then extension kinds as declared.
|
|
@@ -316,6 +284,46 @@ function compileWorkspaceResolved(parsed) {
|
|
|
316
284
|
const identity = `${value.id}@${value.version}`;
|
|
317
285
|
pendingProfiles.push({ input, value, identity, positionFor });
|
|
318
286
|
}
|
|
287
|
+
const alreadyDeclaresPolicy = pendingProfiles.some(({ identity }) => identity === shippedPolicyIdentity);
|
|
288
|
+
if (!alreadyDeclaresPolicy) {
|
|
289
|
+
const selected = documentInputs.some(({ entry }) => {
|
|
290
|
+
const value = entry.value;
|
|
291
|
+
return value.profile === shippedPolicyIdentity;
|
|
292
|
+
});
|
|
293
|
+
const extended = pendingProfiles.some(({ value }) => value.extends === shippedPolicyIdentity);
|
|
294
|
+
if (selected || extended) {
|
|
295
|
+
const input = {
|
|
296
|
+
path: 'yarramate:profile:yarramate/policy@0.1',
|
|
297
|
+
source: shippedPolicySource,
|
|
298
|
+
};
|
|
299
|
+
const { entry, fresh } = parseWorkspaceSource(input);
|
|
300
|
+
const value = entry.value;
|
|
301
|
+
if (entry.schemaDiagnostics.length > 0) {
|
|
302
|
+
profileDiagnostics.push(...entry.schemaDiagnostics);
|
|
303
|
+
}
|
|
304
|
+
else if (!validateProfile(value)) {
|
|
305
|
+
for (const error of validateProfile.errors ?? []) {
|
|
306
|
+
profileDiagnostics.push({
|
|
307
|
+
severity: 'error',
|
|
308
|
+
code: 'YM201',
|
|
309
|
+
message: `Profile schema violation: ${describeSchemaViolation(error)}`,
|
|
310
|
+
path: input.path,
|
|
311
|
+
pointer: error.instancePath || '/',
|
|
312
|
+
line: 1,
|
|
313
|
+
column: 1,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
pendingProfiles.push({
|
|
319
|
+
input,
|
|
320
|
+
value,
|
|
321
|
+
identity: shippedPolicyIdentity,
|
|
322
|
+
positionFor: positionReader(input.source, entry.positions, fresh),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
319
327
|
let unresolvedProfiles = pendingProfiles.sort((left, right) => left.identity.localeCompare(right.identity) ||
|
|
320
328
|
left.input.path.localeCompare(right.input.path));
|
|
321
329
|
while (unresolvedProfiles.length > 0) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const ATTESTATION_PREDICATE_PREFIX = "yarramate/attestation/";
|
|
2
|
+
export declare const attestationClaimValue: (attestation: {
|
|
3
|
+
readonly by: string;
|
|
4
|
+
readonly on: string;
|
|
5
|
+
readonly recordedBy?: string;
|
|
6
|
+
}) => string;
|
|
7
|
+
export interface AttestationClaimParts {
|
|
8
|
+
readonly by: string;
|
|
9
|
+
readonly on: string;
|
|
10
|
+
readonly recordedBy?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const parseAttestationClaimValue: (value: string) => AttestationClaimParts | undefined;
|
|
13
|
+
export interface ConstraintExpectsParts {
|
|
14
|
+
readonly provider: string;
|
|
15
|
+
readonly key: string;
|
|
16
|
+
readonly value: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const parseConstraintExpectsValue: (value: string) => ConstraintExpectsParts | undefined;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const ATTESTATION_PREDICATE_PREFIX = 'yarramate/attestation/';
|
|
2
|
+
// An attestation claim packs the authority, the date it was given, and
|
|
3
|
+
// the recorder when a machine held the pen. A reference carries no
|
|
4
|
+
// spaces and the date is fixed width, so the three parse back out of one
|
|
5
|
+
// value unambiguously wherever a reader needs them.
|
|
6
|
+
export const attestationClaimValue = (attestation) => attestation.recordedBy === undefined
|
|
7
|
+
? `${attestation.by} ${attestation.on}`
|
|
8
|
+
: `${attestation.by} ${attestation.on} ${attestation.recordedBy}`;
|
|
9
|
+
export const parseAttestationClaimValue = (value) => {
|
|
10
|
+
const match = /^(\S+) ([0-9]{4}-[0-9]{2}-[0-9]{2})(?: (.+))?$/.exec(value);
|
|
11
|
+
if (match === null)
|
|
12
|
+
return undefined;
|
|
13
|
+
const recordedBy = match[3];
|
|
14
|
+
return {
|
|
15
|
+
by: match[1],
|
|
16
|
+
on: match[2],
|
|
17
|
+
...(recordedBy === undefined ? {} : { recordedBy }),
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
// Mirrors the compiler's own write-side encoding (ADR 0075): provider and
|
|
21
|
+
// key admit no whitespace, so the first two spaces delimit them and
|
|
22
|
+
// everything after the second space is the expected value verbatim, spaces
|
|
23
|
+
// included. This is the sole authority for decoding the value written at
|
|
24
|
+
// the constraint's `expects` claim — reconciliation.ts delegates here
|
|
25
|
+
// rather than mirroring the regex itself.
|
|
26
|
+
export const parseConstraintExpectsValue = (value) => {
|
|
27
|
+
const match = /^(\S+) (\S+) ([\s\S]+)$/.exec(value);
|
|
28
|
+
if (match === null)
|
|
29
|
+
return undefined;
|
|
30
|
+
return {
|
|
31
|
+
provider: match[1],
|
|
32
|
+
key: match[2],
|
|
33
|
+
value: match[3],
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ResolvedProfileContext, SemanticGraph } from './compiler.js';
|
|
2
|
+
import type { Aspect, Layer } from './profile.js';
|
|
2
3
|
export interface CanvasNode {
|
|
3
4
|
readonly id: string;
|
|
4
5
|
readonly localId: string;
|
|
5
6
|
readonly document: string;
|
|
6
7
|
readonly kind: string;
|
|
7
8
|
readonly kindLabel: string;
|
|
8
|
-
readonly layer:
|
|
9
|
-
readonly aspect:
|
|
9
|
+
readonly layer: Layer | null;
|
|
10
|
+
readonly aspect: Aspect | null;
|
|
10
11
|
readonly name: string;
|
|
11
12
|
readonly description: string | null;
|
|
12
13
|
readonly aka: readonly string[];
|
package/dist/graph-projection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ATTESTATION_PREDICATE_PREFIX, parseAttestationClaimValue, parseConstraintExpectsValue, } from './
|
|
1
|
+
import { ATTESTATION_PREDICATE_PREFIX, parseAttestationClaimValue, parseConstraintExpectsValue, } from './graph-claims.js';
|
|
2
2
|
import { kindLabelOf } from './kind-label.js';
|
|
3
3
|
const CONCEPT_KIND_PREDICATE = 'yarramate/concept/kind';
|
|
4
4
|
const CONCEPT_NAME_PREDICATE = 'yarramate/concept/name';
|
|
@@ -18,6 +18,7 @@ type CatalogueCondition = {
|
|
|
18
18
|
} | {
|
|
19
19
|
readonly condition: 'no-subject-of-kind';
|
|
20
20
|
readonly kinds: readonly string[];
|
|
21
|
+
readonly kindMatching?: 'exact' | 'descendants';
|
|
21
22
|
} | {
|
|
22
23
|
readonly condition: 'no-state-defined';
|
|
23
24
|
} | {
|
|
@@ -26,6 +27,24 @@ type CatalogueCondition = {
|
|
|
26
27
|
readonly direction: 'incoming' | 'outgoing';
|
|
27
28
|
readonly counterpartKinds: readonly string[];
|
|
28
29
|
readonly kindMatching?: 'exact' | 'descendants';
|
|
30
|
+
} | {
|
|
31
|
+
readonly condition: 'has-linkage';
|
|
32
|
+
readonly kinds: readonly string[];
|
|
33
|
+
readonly direction: 'incoming' | 'outgoing' | 'either';
|
|
34
|
+
readonly counterpartKinds: readonly string[];
|
|
35
|
+
readonly kindMatching?: 'exact' | 'descendants';
|
|
36
|
+
} | {
|
|
37
|
+
readonly condition: 'exists-linkage';
|
|
38
|
+
readonly kinds: readonly string[];
|
|
39
|
+
readonly direction: 'incoming' | 'outgoing' | 'either';
|
|
40
|
+
readonly counterpartKinds: readonly string[];
|
|
41
|
+
readonly kindMatching?: 'exact' | 'descendants';
|
|
42
|
+
} | {
|
|
43
|
+
readonly condition: 'missing-constraint';
|
|
44
|
+
readonly kinds: readonly string[];
|
|
45
|
+
readonly kindMatching?: 'exact' | 'descendants';
|
|
46
|
+
} | {
|
|
47
|
+
readonly condition: 'missing-flow-content';
|
|
29
48
|
} | {
|
|
30
49
|
readonly condition: 'missing-reference';
|
|
31
50
|
readonly predicate: string;
|