Check required values for type
attribute
added attributes for required type and achievement return error instead of notRun
This commit is contained in:
parent
677e547add
commit
1fe23b7278
@ -188,7 +188,7 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
|
|||||||
|
|
||||||
//credentialSubject
|
//credentialSubject
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(new CredentialSubjectProbe().run(endorsement.getJson(), ctx));
|
accumulator.add(new CredentialSubjectProbe("EndorsementSubject").run(endorsement.getJson(), ctx));
|
||||||
|
|
||||||
//signatures, proofs
|
//signatures, proofs
|
||||||
probeCount++;
|
probeCount++;
|
||||||
|
@ -170,7 +170,7 @@ public class OB30Inspector extends VCInspector implements SubInspector {
|
|||||||
|
|
||||||
//credentialSubject
|
//credentialSubject
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(new CredentialSubjectProbe().run(ob.getJson(), ctx));
|
accumulator.add(new CredentialSubjectProbe("AchievementSubject", true).run(ob.getJson(), ctx));
|
||||||
|
|
||||||
//signatures, proofs
|
//signatures, proofs
|
||||||
probeCount++;
|
probeCount++;
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package org.oneedtech.inspect.vc.probe;
|
package org.oneedtech.inspect.vc.probe;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.oneedtech.inspect.core.probe.Probe;
|
import org.oneedtech.inspect.core.probe.Probe;
|
||||||
import org.oneedtech.inspect.core.probe.RunContext;
|
import org.oneedtech.inspect.core.probe.RunContext;
|
||||||
import org.oneedtech.inspect.core.report.ReportItems;
|
import org.oneedtech.inspect.core.report.ReportItems;
|
||||||
|
import org.oneedtech.inspect.vc.util.JsonNodeUtil;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
@ -14,8 +17,20 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
|
|||||||
*/
|
*/
|
||||||
public class CredentialSubjectProbe extends Probe<JsonNode> {
|
public class CredentialSubjectProbe extends Probe<JsonNode> {
|
||||||
|
|
||||||
public CredentialSubjectProbe() {
|
/**
|
||||||
|
* Required type to be present.
|
||||||
|
*/
|
||||||
|
private final String requiredType;
|
||||||
|
private boolean achivementRequired;
|
||||||
|
|
||||||
|
public CredentialSubjectProbe(String requiredType) {
|
||||||
|
this(requiredType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CredentialSubjectProbe(String requiredType, boolean achivementRequired) {
|
||||||
super(ID);
|
super(ID);
|
||||||
|
this.requiredType = requiredType;
|
||||||
|
this.achivementRequired = achivementRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -24,18 +39,86 @@ public class CredentialSubjectProbe extends Probe<JsonNode> {
|
|||||||
JsonNode subject = root.get("credentialSubject");
|
JsonNode subject = root.get("credentialSubject");
|
||||||
if(subject == null) return notRun("no credentialSubject node found", ctx); //error reported by schema
|
if(subject == null) return notRun("no credentialSubject node found", ctx); //error reported by schema
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that type contains AchievementSubject
|
||||||
|
*/
|
||||||
|
if (!JsonNodeUtil.asStringList(subject.get("type")).contains(requiredType)) {
|
||||||
|
return error("credentialSubject is not of type \"" + requiredType + "\"", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that we have either .id or .identifier populated
|
* Check that we have either .id or .identifier populated
|
||||||
*/
|
*/
|
||||||
|
if (idAndIdentifierEmpty(subject)) {
|
||||||
|
return error("no id in credentialSubject", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if .identifier is provider, check its type
|
||||||
|
*/
|
||||||
|
if (subject.hasNonNull("identifier")) {
|
||||||
|
List<JsonNode> identifiers = JsonNodeUtil.asNodeList(subject.get("identifier"));
|
||||||
|
for (JsonNode identifier : identifiers) {
|
||||||
|
// check that type contains "IdentityObject"
|
||||||
|
if (!JsonNodeUtil.asStringList(identifier.get("type")).contains("IdentityObject")) {
|
||||||
|
return error("identifier in credentialSubject is not of type \"IdentityObject\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check results
|
||||||
|
*/
|
||||||
|
if (subject.hasNonNull("result")) {
|
||||||
|
List<JsonNode> results = JsonNodeUtil.asNodeList(subject.get("result"));
|
||||||
|
for (JsonNode result : results) {
|
||||||
|
// check that type contains "Result"
|
||||||
|
if (!JsonNodeUtil.asStringList(result.get("type")).contains("Result")) {
|
||||||
|
return error("result in credentialSubject is not of type \"Result\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check achievement result description
|
||||||
|
*/
|
||||||
|
if (subject.hasNonNull("achievement")) {
|
||||||
|
JsonNode achievement = subject.get("achievement");
|
||||||
|
if (achievement.hasNonNull("resultDescription")) {
|
||||||
|
List<JsonNode> resultDescriptions = JsonNodeUtil.asNodeList(achievement.get("resultDescription"));
|
||||||
|
for (JsonNode resultDescription : resultDescriptions) {
|
||||||
|
// check that type contains "ResultDescription"
|
||||||
|
if (!JsonNodeUtil.asStringList(resultDescription.get("type")).contains("ResultDescription")) {
|
||||||
|
return error("resultDescription in achievement of credentialSubject is not of type \"ResultDescription\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (achivementRequired) {
|
||||||
|
return error("missing required achievement in credentialSubject", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that source type contains "Profile"
|
||||||
|
*/
|
||||||
|
if (subject.hasNonNull("source")) {
|
||||||
|
JsonNode source = subject.get("source");
|
||||||
|
// check that type contains "Profile"
|
||||||
|
if (!JsonNodeUtil.asStringList(source.get("type")).contains("Profile")) {
|
||||||
|
return error("source in credentialSubject is not of type \"Profile\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean idAndIdentifierEmpty(JsonNode root) {
|
||||||
JsonNode id = root.get("id");
|
JsonNode id = root.get("id");
|
||||||
if (id != null && id.textValue().strip().length() > 0) return success(ctx);
|
if (id != null && id.textValue().strip().length() > 0) return false;
|
||||||
|
|
||||||
JsonNode identifier = root.get("identifier");
|
JsonNode identifier = root.get("identifier");
|
||||||
if(identifier != null && identifier instanceof ArrayNode
|
if(identifier != null && identifier instanceof ArrayNode
|
||||||
&& ((ArrayNode)identifier).size() > 0) return success(ctx);
|
&& ((ArrayNode)identifier).size() > 0) return false;
|
||||||
|
|
||||||
return error("no id in credentialSubject", ctx);
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String ID = CredentialSubjectProbe.class.getSimpleName();
|
public static final String ID = CredentialSubjectProbe.class.getSimpleName();
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package org.oneedtech.inspect.vc.probe;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.oneedtech.inspect.core.probe.Probe;
|
||||||
|
import org.oneedtech.inspect.core.probe.RunContext;
|
||||||
|
import org.oneedtech.inspect.core.report.ReportItems;
|
||||||
|
import org.oneedtech.inspect.util.resource.UriResource;
|
||||||
|
import org.oneedtech.inspect.vc.util.JsonNodeUtil;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
|
public class IssuerProbe extends Probe<JsonNode> {
|
||||||
|
public IssuerProbe() {
|
||||||
|
super(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReportItems run(JsonNode root, RunContext ctx) throws Exception {
|
||||||
|
JsonNode issuer = root.get("issuer");
|
||||||
|
if(issuer == null) return error("no issuer node found", ctx);
|
||||||
|
|
||||||
|
// check that type contains "Profile"
|
||||||
|
if (!JsonNodeUtil.asStringList(issuer.get("type")).contains("Profile")) {
|
||||||
|
return error("issuer is not of type \"Profile\"", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check url is accessible
|
||||||
|
if (issuer.hasNonNull("url")) {
|
||||||
|
try {
|
||||||
|
UriResource urlResource = new UriResource(new URI(issuer.get("url").asText().strip()));
|
||||||
|
if (!urlResource.exists()) {
|
||||||
|
return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check other identifier
|
||||||
|
if (issuer.hasNonNull("otherIdentifier")) {
|
||||||
|
List<JsonNode> otherIdentifiers = JsonNodeUtil.asNodeList(issuer.get("otherIdentifier"));
|
||||||
|
for (JsonNode otherIdentifier : otherIdentifiers) {
|
||||||
|
// check that type contains "IdentityObject"
|
||||||
|
if (!JsonNodeUtil.asStringList(otherIdentifier.get("type")).contains("IdentityObject")) {
|
||||||
|
return error("otherIdentifier in issuer is not of type \"IdentityObject\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check parent issuer
|
||||||
|
if (issuer.hasNonNull("parentOrg")) {
|
||||||
|
JsonNode parentOrg = issuer.get("parentOrg");
|
||||||
|
// check that type contains "Profile"
|
||||||
|
if (!JsonNodeUtil.asStringList(parentOrg.get("type")).contains("Profile")) {
|
||||||
|
return error("parentOrg in issuer is not of type \"Profile\"", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ID = IssuerProbe.class.getSimpleName();
|
||||||
|
|
||||||
|
}
|
@ -11,6 +11,7 @@ import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe;
|
|||||||
import org.oneedtech.inspect.core.report.Report;
|
import org.oneedtech.inspect.core.report.Report;
|
||||||
import org.oneedtech.inspect.test.PrintHelper;
|
import org.oneedtech.inspect.test.PrintHelper;
|
||||||
import org.oneedtech.inspect.vc.probe.ContextPropertyProbe;
|
import org.oneedtech.inspect.vc.probe.ContextPropertyProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.CredentialSubjectProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.ExpirationProbe;
|
import org.oneedtech.inspect.vc.probe.ExpirationProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.IssuanceProbe;
|
import org.oneedtech.inspect.vc.probe.IssuanceProbe;
|
||||||
@ -191,6 +192,66 @@ public class OB30Tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonInvalidCredentialSubjectType() {
|
||||||
|
//add a dumb value to .type and remove the ob type
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_TYPE.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
// assertFatalCount(report, 1);
|
||||||
|
assertHasProbeID(report, CredentialSubjectProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonInvalidCredentialSubjectIdentifierType() {
|
||||||
|
//add a dumb value to .type and remove the ob type
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_IDENTIFIER_TYPE.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
// assertFatalCount(report, 1);
|
||||||
|
assertHasProbeID(report, CredentialSubjectProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonInvalidCredentialSubjectResultType() {
|
||||||
|
//add a dumb value to .type and remove the ob type
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_RESULT_TYPE.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
// assertFatalCount(report, 1);
|
||||||
|
assertHasProbeID(report, CredentialSubjectProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonInvalidCredentialSubjectAchievementResultDescriptionType() {
|
||||||
|
//add a dumb value to .type and remove the ob type
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_ACHIEVEMENT_RESULT_DESCRIPTION_TYPE.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
// assertFatalCount(report, 1);
|
||||||
|
assertHasProbeID(report, CredentialSubjectProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonInvalidCredentialSubjectProfileType() {
|
||||||
|
//add a dumb value to .type and remove the ob type
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_PROFILE_TYPE.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
// assertFatalCount(report, 1);
|
||||||
|
assertHasProbeID(report, CredentialSubjectProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Disabled //TODO IssuanceVerifierProbe is not run because FATAL: InvalidSignature terminates
|
@Disabled //TODO IssuanceVerifierProbe is not run because FATAL: InvalidSignature terminates
|
||||||
@Test
|
@Test
|
||||||
void testSimpleJsonNotIssued() {
|
void testSimpleJsonNotIssued() {
|
||||||
|
@ -14,6 +14,11 @@ public class Samples {
|
|||||||
public final static Sample SIMPLE_DID_METHOD_JSON = new Sample("ob30/simple-did-method.json", true);
|
public final static Sample SIMPLE_DID_METHOD_JSON = new Sample("ob30/simple-did-method.json", true);
|
||||||
public final static Sample SIMPLE_JSON_NOPROOF = new Sample("ob30/simple-noproof.json", false);
|
public final static Sample SIMPLE_JSON_NOPROOF = new Sample("ob30/simple-noproof.json", false);
|
||||||
public final static Sample SIMPLE_JSON_UNKNOWN_TYPE = new Sample("ob30/simple-err-type.json", false);
|
public final static Sample SIMPLE_JSON_UNKNOWN_TYPE = new Sample("ob30/simple-err-type.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_TYPE = new Sample("ob30/simple-err-credential-subject-type.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_IDENTIFIER_TYPE = new Sample("ob30/simple-err-credential-subject-identifier-type.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_RESULT_TYPE = new Sample("ob30/simple-err-credential-subject-result-type.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_ACHIEVEMENT_RESULT_DESCRIPTION_TYPE = new Sample("ob30/simple-err-credential-subject-achievement-result-description-type.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_UNKNOWN_CREDENTIAL_SUBJECT_PROFILE_TYPE = new Sample("ob30/simple-err-credential-subject-profile-type.json", false);
|
||||||
public final static Sample SIMPLE_JSON_PROOF_METHOD_ERROR = new Sample("ob30/simple-err-proof-method.json", false);
|
public final static Sample SIMPLE_JSON_PROOF_METHOD_ERROR = new Sample("ob30/simple-err-proof-method.json", false);
|
||||||
public final static Sample SIMPLE_JSON_PROOF_METHOD_NO_SCHEME_ERROR = new Sample("ob30/simple-err-proof-method-no-scheme.json", false);
|
public final static Sample SIMPLE_JSON_PROOF_METHOD_NO_SCHEME_ERROR = new Sample("ob30/simple-err-proof-method-no-scheme.json", false);
|
||||||
public final static Sample SIMPLE_JSON_PROOF_METHOD_UNKNOWN_SCHEME_ERROR = new Sample("ob30/simple-err-proof-method-unknown-scheme.json", false);
|
public final static Sample SIMPLE_JSON_PROOF_METHOD_UNKNOWN_SCHEME_ERROR = new Sample("ob30/simple-err-proof-method-unknown-scheme.json", false);
|
||||||
|
@ -0,0 +1,188 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.com/credentials/3527",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.com/issuers/876543",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example Corp"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Teamwork Badge",
|
||||||
|
"credentialSubject": {
|
||||||
|
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||||
|
"type": [
|
||||||
|
"AchievementSubject"
|
||||||
|
],
|
||||||
|
"achievement": {
|
||||||
|
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||||
|
"type": [
|
||||||
|
"Achievement"
|
||||||
|
],
|
||||||
|
"criteria": {
|
||||||
|
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||||
|
},
|
||||||
|
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||||
|
"name": "Teamwork",
|
||||||
|
"resultDescription": [
|
||||||
|
{
|
||||||
|
"id": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||||
|
"type": "ResultDescription",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"allowedValue": [
|
||||||
|
"D",
|
||||||
|
"C",
|
||||||
|
"B",
|
||||||
|
"A"
|
||||||
|
],
|
||||||
|
"name": "Final Project Grade",
|
||||||
|
"requiredValue": "C",
|
||||||
|
"resultType": "LetterGrade"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "urn:uuid:a70ddc6a-4c4a-4bd8-8277-cb97c79f40c5",
|
||||||
|
"type": "ResultDescription",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"allowedValue": [
|
||||||
|
"D",
|
||||||
|
"C",
|
||||||
|
"B",
|
||||||
|
"A"
|
||||||
|
],
|
||||||
|
"name": "Final Project Grade",
|
||||||
|
"requiredLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||||
|
"resultType": "RubricCriterionLevel",
|
||||||
|
"rubricCriterionLevel": [
|
||||||
|
{
|
||||||
|
"id": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||||
|
"type": "RubricCriterionLevel",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFRubricCriterionLevel",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/mastered"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "The author demonstrated...",
|
||||||
|
"level": "Mastered",
|
||||||
|
"name": "Mastery",
|
||||||
|
"points": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "urn:uuid:6b84b429-31ee-4dac-9d20-e5c55881f80e",
|
||||||
|
"type": "RubricCriterionLevel",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFRubricCriterionLevel",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/basic"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "The author demonstrated...",
|
||||||
|
"level": "Basic",
|
||||||
|
"name": "Basic",
|
||||||
|
"points": "4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "urn:uuid:b07c0387-f2d6-4b65-a3f4-f4e4302ea8f7",
|
||||||
|
"type": "InvalidResultDescription",
|
||||||
|
"name": "Project Status",
|
||||||
|
"resultType": "Status"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"result": [
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"Result"
|
||||||
|
],
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||||
|
"value": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"Result"
|
||||||
|
],
|
||||||
|
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"Result"
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||||
|
"status": "Completed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-11-16T18:54:22Z",
|
||||||
|
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.com/credentials/3527",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.com/issuers/876543",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example Corp"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Teamwork Badge",
|
||||||
|
"credentialSubject": {
|
||||||
|
"identifier": [{
|
||||||
|
"type": "InvalidIdentityObject",
|
||||||
|
"hashed": true,
|
||||||
|
"identityHash": "asdjhsadas",
|
||||||
|
"identityType": "lisSourcedId"
|
||||||
|
}],
|
||||||
|
"type": [
|
||||||
|
"AchievementSubject"
|
||||||
|
],
|
||||||
|
"achievement": {
|
||||||
|
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||||
|
"type": [
|
||||||
|
"Achievement"
|
||||||
|
],
|
||||||
|
"criteria": {
|
||||||
|
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||||
|
},
|
||||||
|
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||||
|
"name": "Teamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-11-16T18:54:22Z",
|
||||||
|
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.com/credentials/3527",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.com/issuers/876543",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example Corp"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Teamwork Badge",
|
||||||
|
"credentialSubject": {
|
||||||
|
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||||
|
"type": [
|
||||||
|
"AchievementSubject"
|
||||||
|
],
|
||||||
|
"achievement": {
|
||||||
|
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||||
|
"type": [
|
||||||
|
"Achievement"
|
||||||
|
],
|
||||||
|
"criteria": {
|
||||||
|
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||||
|
},
|
||||||
|
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||||
|
"name": "Teamwork"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"id": "https://school.edu/issuers/201234",
|
||||||
|
"type": "InvalidProfile",
|
||||||
|
"name": "1EdTech College of Arts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-11-16T18:54:22Z",
|
||||||
|
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.com/credentials/3527",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.com/issuers/876543",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example Corp"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Teamwork Badge",
|
||||||
|
"credentialSubject": {
|
||||||
|
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||||
|
"type": [
|
||||||
|
"AchievementSubject"
|
||||||
|
],
|
||||||
|
"achievement": {
|
||||||
|
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||||
|
"type": [
|
||||||
|
"Achievement"
|
||||||
|
],
|
||||||
|
"criteria": {
|
||||||
|
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||||
|
},
|
||||||
|
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||||
|
"name": "Teamwork"
|
||||||
|
},
|
||||||
|
"result": [
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"Result"
|
||||||
|
],
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||||
|
"value": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"InvalidResult"
|
||||||
|
],
|
||||||
|
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||||
|
"alignment": [
|
||||||
|
{
|
||||||
|
"type": "Alignment",
|
||||||
|
"targetCode": "project",
|
||||||
|
"targetDescription": "Project description",
|
||||||
|
"targetName": "Final Project",
|
||||||
|
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||||
|
"targetType": "CFItem",
|
||||||
|
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"Result"
|
||||||
|
],
|
||||||
|
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||||
|
"status": "Completed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-11-16T18:54:22Z",
|
||||||
|
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.com/credentials/3527",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.com/issuers/876543",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example Corp"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Teamwork Badge",
|
||||||
|
"credentialSubject": {
|
||||||
|
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||||
|
"type": [
|
||||||
|
"InvalidAchievementSubject"
|
||||||
|
],
|
||||||
|
"achievement": {
|
||||||
|
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||||
|
"type": [
|
||||||
|
"Achievement"
|
||||||
|
],
|
||||||
|
"criteria": {
|
||||||
|
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||||
|
},
|
||||||
|
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||||
|
"name": "Teamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-11-16T18:54:22Z",
|
||||||
|
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user