Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ consumed fragment files.
Create a fragment for PR or issue `100` using the configured SignifyPy types:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
./venv/bin/python -m towncrier create --dir newsfragments \
--content "Documented the repository-secret PyPI publish flow." \
100.doc.md
Expand All @@ -84,7 +84,7 @@ cd /Users/kbull/code/keri/kentbull/signifypy
Another example for a bug fix:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
./venv/bin/python -m towncrier create --dir newsfragments \
--content "Fixed release workflow auth to use the repository secret PYPI_API_TOKEN." \
101.fixed.md
Expand All @@ -93,7 +93,7 @@ cd /Users/kbull/code/keri/kentbull/signifypy
You can also create the fragment file yourself if that is faster:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
cat > newsfragments/102.misc.md <<'EOF'
Clarified the maintainer release runbook with concrete Towncrier examples.
EOF
Expand All @@ -102,22 +102,22 @@ EOF
Preview the unreleased changelog without modifying tracked files:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
./venv/bin/python -m towncrier build --draft --version 0.4.1
```

Build the actual `0.4.1` changelog entry during release preparation:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
./venv/bin/python -m towncrier build --yes --version 0.4.1
```

Or let the maintained release-prep target do the version bump, lock refresh,
Towncrier build, and release commit together:

```bash
cd /Users/kbull/code/keri/kentbull/signifypy
cd signifypy
make release-patch
```

Expand Down
2 changes: 1 addition & 1 deletion scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The old manual workflow scripts that used to live in this directory have been
retired.

Those scenarios now belong to the pytest-managed integration harness in
[`tests/integration`](/Users/kbull/code/keri/kentbull/signifypy/tests/integration),
[`tests/integration`](/signifypy/tests/integration),
which starts witnesses, KERIA, and `vlei-server` itself instead of requiring
multiple external terminal sessions.

Expand Down
12 changes: 11 additions & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from contextlib import contextmanager
import json
import os
import shutil
import socket
import subprocess
from pathlib import Path
Expand Down Expand Up @@ -66,6 +67,7 @@ def _dependency_root(dependency):
KERIPY_ROOT = _dependency_root(KERIPY)
KERIA_ROOT = _dependency_root(KERIA)
VLEI_ROOT = _dependency_root(VLEI)
UNTARGETED_SCHEMA_PATH = SIGNIFYPY_ROOT / "tests" / "schema" / "optional-issuee-attestation.json"
SIGNIFYPY_PYTHON = Path(os.getenv("SIGNIFYPY_INTEGRATION_SIGNIFYPY_PYTHON", SIGNIFYPY_ROOT / "venv" / "bin" / "python")).expanduser()
KERIA_PYTHON = Path(os.getenv("SIGNIFYPY_INTEGRATION_KERIA_PYTHON", KERIA_ROOT / "venv" / "bin" / "python")).expanduser()
VLEI_PYTHON = Path(os.getenv("SIGNIFYPY_INTEGRATION_VLEI_PYTHON", VLEI_ROOT / "venv" / "bin" / "python")).expanduser()
Expand Down Expand Up @@ -383,6 +385,7 @@ def _launch_live_stack(live_stack: dict):
vlei_python = _require_python(VLEI_PYTHON, "vLEI")
runtime_root = live_stack["runtime_root"]
config_root = live_stack["config_root"]
schema_dir = _prepare_schema_directory(runtime_root)

_write_canonical_witness_configs(config_root, live_stack)
_write_keria_config(config_root, live_stack)
Expand Down Expand Up @@ -465,7 +468,7 @@ def _launch_live_stack(live_stack: dict):
"-u",
str(VLEI_SERVER_SCRIPT),
"--schema-dir",
str(VLEI_ROOT / "schema" / "acdc"),
str(schema_dir),
"--cred-dir",
str(VLEI_ROOT / "samples" / "acdc"),
"--oobi-dir",
Expand Down Expand Up @@ -581,3 +584,10 @@ def isolated_client_factory(isolated_live_stack):
boundaries. Most business-workflow tests should stay on `client_factory`.
"""
return _client_factory(isolated_live_stack)
def _prepare_schema_directory(runtime_root: Path) -> Path:
"""Overlay integration-owned schemas on the pinned vLEI schema set."""
schema_dir = runtime_root / "schemas"
shutil.copytree(VLEI_ROOT / "schema" / "acdc", schema_dir)
shutil.copy2(UNTARGETED_SCHEMA_PATH, schema_dir / UNTARGETED_SCHEMA_PATH.name)
return schema_dir

2 changes: 2 additions & 0 deletions tests/integration/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
"""

QVI_SCHEMA_SAID = "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao"
UNTARGETED_ATTESTATION_SCHEMA_SAID = "EAv8omZ-o3Pk45h72_WnIpt6LTWNzc8hmLjeblpxB9vz"
ADDITIONAL_SCHEMA_OOBI_SAIDS = {
"legal-entity": "ENPXp1vQzRF6JwIuS-mp2U8Uf1MoADoP_GqQ62VsDZWY",
"ecr-auth": "EH6ekLjSr8V32WyFbGe1zXjTzFs9PkTYmupJ9H65O14g",
"ecr": "EEy9PkikFcANV1l7EHukCeXqrzT1hNZjGlUk7wuMO5jw",
"oor-auth": "EKA57bKBKxr_kN7iN5i7lMUxpMG-s19dRcmov1iDxz-E",
"oor": "EBNaNu-M9P5cgrnfl2Fvymy4E_jvxxyjb70PRtiANlJy",
"untargeted-attestation": UNTARGETED_ATTESTATION_SCHEMA_SAID,
}

WITNESS_AIDS = [
Expand Down
88 changes: 88 additions & 0 deletions tests/integration/test_untargeted_ipex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""Regression coverage for presenting untargeted ACDCs through IPEX."""

from __future__ import annotations

import pytest

from .constants import TEST_WITNESS_AIDS, UNTARGETED_ATTESTATION_SCHEMA_SAID
from .helpers import (
alias,
create_identifier,
create_registry,
resolve_agent_oobi,
resolve_schema_oobi,
send_credential_grant,
submit_admit,
wait_for_credential,
wait_for_notification,
wait_for_operation,
)


pytestmark = pytest.mark.integration


def test_untargeted_acdc_grant_delivers_artifacts_to_disclosee(client_factory):
"""Present an ACDC without an issuee to an independently addressed disclosee.

The disclosee intentionally does not resolve the issuer's OOBI first. An
IPEX Grant is responsible for delivering the issuer KEL and the credential
artifacts needed to validate the embedded untargeted attestation.
"""
issuer_client = client_factory()
disclosee_client = client_factory()
issuer_name = alias("untargeted-issuer")
disclosee_name = alias("untargeted-disclosee")
registry_name = alias("untargeted-registry")

issuer = create_identifier(issuer_client, issuer_name, wits=TEST_WITNESS_AIDS)
disclosee = create_identifier(disclosee_client, disclosee_name, wits=TEST_WITNESS_AIDS)

# The issuer must know where to send the Grant. Do not resolve the reverse
# direction: successful presentation must bootstrap the disclosee with the
# issuer artifacts carried by the Grant workflow.
resolve_agent_oobi(disclosee_client, disclosee_name, issuer_client)
resolve_schema_oobi(issuer_client, UNTARGETED_ATTESTATION_SCHEMA_SAID)
resolve_schema_oobi(disclosee_client, UNTARGETED_ATTESTATION_SCHEMA_SAID)

create_registry(issuer_client, issuer_name, registry_name)
issued = issuer_client.credentials().issue(
issuer_name,
registry_name,
data={"claim": "An issuer-authored observation addressed to whom it may concern."},
schema=UNTARGETED_ATTESTATION_SCHEMA_SAID,
recipient=None,
edges={},
rules={},
)
wait_for_operation(issuer_client, issued.op())

assert issued.acdc.sad["i"] == issuer["prefix"]
assert "i" not in issued.acdc.sad["a"]

send_credential_grant(
issuer_client,
issuer_name=issuer_name,
recipient=disclosee["prefix"],
creder=issued.acdc,
iserder=issued.iss,
anc=issued.anc,
sigs=issued.sigs,
)

grant_note = wait_for_notification(
disclosee_client,
"/exn/ipex/grant",
timeout=30.0,
)
submit_admit(
disclosee_client,
holder_name=disclosee_name,
issuer_prefix=issuer["prefix"],
notification=grant_note,
)
received = wait_for_credential(disclosee_client, issued.acdc.said)

assert received["sad"]["d"] == issued.acdc.said
assert received["sad"]["i"] == issuer["prefix"]
assert "i" not in received["sad"]["a"]
45 changes: 45 additions & 0 deletions tests/schema/optional-issuee-attestation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$id": "EAv8omZ-o3Pk45h72_WnIpt6LTWNzc8hmLjeblpxB9vz",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Optional Issuee",
"description": "A credential with an optional issuee",
"credentialType": "UntargetedAttestation",
"properties": {
"v": {"type": "string"},
"d": {"type": "string"},
"i": {"type": "string"},
"ri": {
"description": "credential status registry",
"type": "string"
},
"s": {
"description": "schema SAID",
"type": "string"
},
"a": {
"properties": {
"d": {"type": "string"},
"i": {"type": "string"},
"dt": {
"format": "date-time",
"type": "string"
},
"claim": {"type": "string"}
},
"additionalProperties": false,
"required": ["dt", "claim"],
"type": "object"
},
"e": {
"description": "edges block",
"type": "object"
},
"r": {
"type": "object",
"description": "rules block"
}
},
"additionalProperties": false,
"required": ["i", "ri", "s", "d", "e", "r"],
"type": "object"
}
Loading