diff --git a/specification/energy-credentials/electricity-credential/context.jsonld b/specification/energy-credentials/electricity-credential/context.jsonld new file mode 100644 index 00000000..58660e39 --- /dev/null +++ b/specification/energy-credentials/electricity-credential/context.jsonld @@ -0,0 +1,303 @@ +{ + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type", + "schema": "https://schema.org/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "deg": "https://schema.beckn.io/deg#", + "CustomerCredential": { + "@id": "deg:CustomerCredential", + "@context": { + "@version": 1.1, + "@protected": true, + "id": "@id", + "type": "@type" + } + }, + "customerProfile": { + "@id": "deg:customerProfile", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "customerNumber": { + "@id": "deg:customerNumber", + "@type": "xsd:string" + }, + "meterNumber": { + "@id": "deg:meterNumber", + "@type": "xsd:string" + }, + "meterType": { + "@id": "deg:meterType", + "@type": "xsd:string" + }, + "idRef": { + "@id": "deg:idRef", + "@type": "@id", + "@context": { + "issuedBy": { + "@id": "deg:issuedBy", + "@type": "@id" + }, + "subjectId": { + "@id": "deg:subjectId", + "@type": "xsd:string" + } + } + } + } + }, + "customerDetails": { + "@id": "deg:customerDetails", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "fullName": { + "@id": "schema:name", + "@type": "xsd:string" + }, + "serviceConnectionDate": { + "@id": "deg:serviceConnectionDate", + "@type": "xsd:dateTime" + }, + "installationAddress": { + "@id": "beckn:Location", + "@type": "@id", + "@context": { + "beckn": "https://schema.beckn.io/", + "descriptor": { + "@id": "beckn:descriptor", + "@type": "@id", + "@context": { + "name": { + "@id": "beckn:name", + "@type": "xsd:string" + }, + "code": { + "@id": "beckn:code", + "@type": "xsd:string" + }, + "short_desc": { + "@id": "beckn:short_desc", + "@type": "xsd:string" + }, + "long_desc": { + "@id": "beckn:long_desc", + "@type": "xsd:string" + } + } + }, + "map_url": { + "@id": "beckn:map_url", + "@type": "@id" + }, + "gps": { + "@id": "beckn:gps", + "@type": "xsd:string" + }, + "address": { + "@id": "beckn:address", + "@type": "xsd:string" + }, + "city": { + "@id": "beckn:city", + "@type": "@id", + "@context": { + "name": { + "@id": "beckn:name", + "@type": "xsd:string" + }, + "code": { + "@id": "beckn:code", + "@type": "xsd:string" + } + } + }, + "district": { + "@id": "beckn:district", + "@type": "xsd:string" + }, + "state": { + "@id": "beckn:state", + "@type": "@id", + "@context": { + "name": { + "@id": "beckn:name", + "@type": "xsd:string" + }, + "code": { + "@id": "beckn:code", + "@type": "xsd:string" + } + } + }, + "country": { + "@id": "beckn:country", + "@type": "@id", + "@context": { + "name": { + "@id": "beckn:name", + "@type": "xsd:string" + }, + "code": { + "@id": "beckn:code", + "@type": "xsd:string" + } + } + }, + "area_code": { + "@id": "beckn:area_code", + "@type": "xsd:string" + }, + "circle": { + "@id": "beckn:circle", + "@type": "@id", + "@context": { + "gps": { + "@id": "beckn:gps", + "@type": "xsd:string" + }, + "radius": { + "@id": "beckn:radius", + "@type": "@id" + } + } + }, + "polygon": { + "@id": "beckn:polygon", + "@type": "xsd:string" + }, + "3dspace": { + "@id": "beckn:3dspace", + "@type": "xsd:string" + }, + "rating": { + "@id": "beckn:rating", + "@type": "xsd:string" + }, + "openLocationCode": { + "@id": "deg:openLocationCode", + "@type": "xsd:string" + } + } + } + } + }, + "consumptionProfile": { + "@id": "deg:consumptionProfile", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "premisesType": { + "@id": "deg:premisesType", + "@type": "xsd:string" + }, + "connectionType": { + "@id": "deg:connectionType", + "@type": "xsd:string" + }, + "sanctionedLoadKW": { + "@id": "deg:sanctionedLoadKW", + "@type": "xsd:decimal" + }, + "tariffCategoryCode": { + "@id": "deg:tariffCategoryCode", + "@type": "xsd:string" + } + } + }, + "generationProfile": { + "@id": "deg:generationProfile", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "assetId": { + "@id": "deg:assetId", + "@type": "xsd:string" + }, + "generationType": { + "@id": "deg:generationType", + "@type": "xsd:string" + }, + "capacityKW": { + "@id": "deg:capacityKW", + "@type": "xsd:decimal" + }, + "commissioningDate": { + "@id": "deg:commissioningDate", + "@type": "xsd:dateTime" + }, + "manufacturer": { + "@id": "schema:manufacturer", + "@type": "xsd:string" + }, + "modelNumber": { + "@id": "deg:modelNumber", + "@type": "xsd:string" + } + } + }, + "storageProfile": { + "@id": "deg:storageProfile", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "assetId": { + "@id": "deg:storageAssetId", + "@type": "xsd:string" + }, + "storageCapacityKWh": { + "@id": "deg:storageCapacityKWh", + "@type": "xsd:decimal" + }, + "powerRatingKW": { + "@id": "deg:powerRatingKW", + "@type": "xsd:decimal" + }, + "commissioningDate": { + "@id": "deg:storageCommissioningDate", + "@type": "xsd:dateTime" + }, + "storageType": { + "@id": "deg:storageType", + "@type": "xsd:string" + } + } + }, + "idRef": { + "@id": "deg:idRef", + "@type": "@id", + "@context": { + "issuedBy": { + "@id": "deg:issuedBy", + "@type": "@id" + }, + "subjectId": { + "@id": "deg:subjectId", + "@type": "xsd:string" + } + } + }, + "credentialStatus": { + "@id": "deg:credentialStatus", + "@type": "@id", + "@context": { + "statusPurpose": { + "@id": "deg:statusPurpose", + "@type": "xsd:string" + }, + "statusListCredential": { + "@id": "deg:statusListCredential", + "@type": "@id" + } + } + } + } +} diff --git a/specification/energy-credentials/electricity-credential/example.json b/specification/energy-credentials/electricity-credential/example.json new file mode 100644 index 00000000..c2968dc9 --- /dev/null +++ b/specification/energy-credentials/electricity-credential/example.json @@ -0,0 +1,102 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schema.org/", + "https://schema.beckn.io/Location/2.0/context.jsonld", + "https://schema.beckn.io/deg/CustomerCredential/context.jsonld", + "https://schema.beckn.io/deg/CustomerProfile/context.jsonld", + "https://schema.beckn.io/deg/CustomerDetails/context.jsonld", + "https://schema.beckn.io/deg/ConsumptionProfile/context.jsonld", + "https://schema.beckn.io/deg/GenerationProfile/context.jsonld", + "https://schema.beckn.io/deg/StorageProfile/context.jsonld" + ], + "id": "urn:uuid:e5f6a7b8-9012-34ab-cdef-567890123456", + "type": [ + "VerifiableCredential", + "CustomerCredential" + ], + "issuer": { + "id": "https://example-utility.com/issuers/energy-dept", + "name": "Example Energy Utility", + "idRef": { + "issuedBy": "did:web:exreg.gov", + "subjectId": "exreg.gov:AABPC00001" + } + }, + "validFrom": "2025-01-13T10:30:00-05:00", + "validUntil": "2026-01-13T10:30:00-05:00", + "credentialStatus": { + "id": "https://dedi.global/dedi/lookup/example-utility.com/vc-revocation-registry/e5f6a7b8-9012-34ab-cdef-567890123456", + "type": "dedi", + "statusPurpose": "revocation", + "statusListCredential": "https://dedi.global/dedi/query/example-utility.com/vc-revocation-registry" + }, + "credentialSubject": { + "id": "did:example:customer:abc123", + "customerProfile": { + "customerNumber": "UTIL-2025-001234567", + "meterNumber": "MET2025789456123", + "meterType": "AMR", + "idRef": { + "issuedBy": "did:web:ssa.gov", + "subjectId": "ssa.gov:XXX-XX-1234" + } + }, + "customerDetails": { + "fullName": "Jane Doe", + "installationAddress": { + "id": "LOC-001", + "descriptor": { + "name": "Jane Doe Residence", + "short_desc": "Residential installation at 123 Energy Street" + }, + "gps": "37.7749,-122.4194", + "address": "123 Energy Street, Unit 4", + "city": { + "name": "Metro City", + "code": "METRO" + }, + "district": "Metro District", + "state": { + "name": "Example State", + "code": "EX" + }, + "country": { + "name": "United States", + "code": "US" + }, + "area_code": "12345", + "openLocationCode": "849VCWC8+R9" + }, + "serviceConnectionDate": "2025-01-10T00:00:00-05:00" + }, + "consumptionProfile": { + "premisesType": "Residential", + "connectionType": "Single-phase", + "sanctionedLoadKW": 5, + "tariffCategoryCode": "RES-01" + }, + "generationProfile": { + "assetId": "DER-SOLAR-001", + "generationType": "Solar", + "capacityKW": 3, + "commissioningDate": "2025-01-12T00:00:00-05:00", + "manufacturer": "SunPower Corporation", + "modelNumber": "SPR-X22-360" + }, + "storageProfile": { + "assetId": "BESS-001", + "storageCapacityKWh": 10, + "powerRatingKW": 5, + "commissioningDate": "2025-01-12T00:00:00-05:00", + "storageType": "LithiumIon" + } + }, + "proof": { + "type": "Ed25519Signature2020", + "created": "2025-01-13T10:30:00-05:00", + "verificationMethod": "https://example-utility.com/issuers/energy-dept#key-1", + "proofPurpose": "assertionMethod", + "proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndTaXoT..." + } +} diff --git a/specification/energy-credentials/electricity-credential/readme.md b/specification/energy-credentials/electricity-credential/readme.md new file mode 100644 index 00000000..180eb716 --- /dev/null +++ b/specification/energy-credentials/electricity-credential/readme.md @@ -0,0 +1,181 @@ +# Customer Credential + +## Overview + +The **Customer Credential** is a unified W3C Verifiable Credential (VC Data Model 2.0) that combines five equal-level profile sections into a single `credentialSubject` object. The customer's DID (`id`) is optional per the W3C VC Data Model, and the five profiles sit as equal-level sibling properties. + +This credential is issued per meter — each meter will have its own credential. + +## Credential Structure + +``` +credentialSubject +├── id (optional customer DID) +├── customerProfile (required — identity: meter, customer number, idRef) +├── customerDetails (required — name, address, connection date) +├── consumptionProfile (optional — premises, connection type, load, tariff) +├── generationProfile (optional — DER type, capacity, commissioning) +└── storageProfile (optional — battery capacity, power rating, type) +``` + +## Issuer + +The credential is issued by energy providers. The issuer object contains: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | URI | Yes | DID or URL of the issuing provider | +| `name` | string | Yes | Name of the provider | +| `idRef` | object | No | (Any) Identity reference — see [idRef](#idref) | + +Example: +```json +"issuer": { + "id": "did:web:bescom.karnataka.gov.in", + "name": "BESCOM - Bangalore Electricity Supply Company", + "idRef": { + "issuedBy": "did:web:kerc.karnataka.gov.in", + "subjectId": "kerc.karnataka.gov.in:AABPC12345" + } +} +``` + +## Validity Period + +Per the [W3C VC Data Model 2.0 validity period](https://www.w3.org/TR/2025/REC-vc-data-model-2.0-20250515/#validity-period), this credential uses: + +- **`validFrom`** (required) — date-time from which the credential is valid +- **`validUntil`** (optional) — date-time until which the credential is valid + +All date-time values include an explicit timezone offset (e.g., `2025-01-13T10:30:00-05:00`). + +## Revocation + +Credential revocation is managed via DeDi. See [credentialStatus](../readme.md#credentialstatus) in the top-level readme. + +## Profile Sections + +### customerProfile + +Core customer identity fields: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `customerNumber` | string | Yes | Full customer account number assigned by the utility | +| `meterNumber` | string | Yes | Unique meter serial number | +| `meterType` | enum | Yes | Type of meter — see [meterType enum](#metertype-enum) | +| `idRef` | object | No | External identity reference (e.g., government ID) — see [idRef](#idref) | + +#### meterType enum + +Values derived from Green Button / ESPI meter kind classifications: + +| Value | Description | +|-------|-------------| +| `AMR` | Automated Meter Reading | +| `AMI` | Advanced Metering Infrastructure (smart meter) | +| `Electromechanical` | Traditional electromechanical meter | +| `Forward` | Forward-only (import) meter | +| `Reverse` | Reverse-only (export) meter | +| `Bidirectional` | Bidirectional meter (import + export) | +| `Prepaid` | Prepaid/token-based meter | +| `NetMeter` | Net metering meter | +| `Other` | Other meter type | + +### customerDetails + +Personal and address information: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `fullName` | string | Yes | Full name of the customer as per ID proof | +| `installationAddress` | object | Yes | Address of the installation (see below) | +| `serviceConnectionDate` | date-time | Yes | Date and time when the electricity connection was activated | + +#### installationAddress + +Follows the [beckn Location schema](https://github.com/beckn/protocol-specifications/blob/master/schema/Location.yaml) with an additional `openLocationCode` field. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | No | Unique identifier for the location | +| `descriptor` | object | No | Physical description of the location (`name`, `code`, `short_desc`, `long_desc`) | +| `map_url` | string (uri) | No | URL to the map of the location | +| `gps` | string | No | GPS coordinates as `"lat,lng"` string (e.g., `"12.9716,77.5946"`) | +| `address` | string | Yes | Complete postal address of the installation | +| `city` | object | No | City — `{ name: string, code: string }` | +| `district` | string | No | District or county name | +| `state` | object | No | State — `{ name: string, code: string }` | +| `country` | object | Yes | Country — `{ name: string, code: string }` (ISO 3166-1 alpha-2 code required) | +| `area_code` | string | Yes | Area code or postal/ZIP code | +| `circle` | object | No | Circular geo-fence — `{ gps: string, radius: Scalar }` | +| `polygon` | string | No | Boundary polygon of the location | +| `3dspace` | string | No | Three dimensional region describing the location | +| `rating` | string | No | Rating of the location | +| `openLocationCode` | string | No | Open Location Code (OLC) for the installation location | + +The address object aligns with the [beckn protocol Location schema](https://github.com/beckn/protocol-specifications/blob/master/schema/Location.yaml) and reuses [schema.org](https://schema.org/) vocabulary where applicable. + +### consumptionProfile + +Connection and consumption characteristics: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `premisesType` | enum | Yes | `Residential`, `Commercial`, `Industrial`, or `Agricultural` | +| `connectionType` | enum | Yes | `Single-phase` or `Three-phase` | +| `sanctionedLoadKW` | number | Yes | Sanctioned electrical load in kW | +| `tariffCategoryCode` | string | Yes | Billing/tariff category code | + +### generationProfile + +DER generation capability: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `assetId` | string | No | Unique identifier for the generation asset | +| `generationType` | enum | Yes | `Solar`, `Wind`, `MicroHydro`, or `Other` | +| `capacityKW` | number | Yes | Installed generation capacity in kW | +| `commissioningDate` | date-time | Yes | Date and time when the system was activated | +| `manufacturer` | string | No | Equipment manufacturer | +| `modelNumber` | string | No | Equipment model number | + +### storageProfile + +Battery/energy storage capability: + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `assetId` | string | No | Unique identifier for the storage asset | +| `storageCapacityKWh` | number | Yes | Storage capacity in kWh | +| `powerRatingKW` | number | Yes | Charge/discharge power rating in kW | +| `commissioningDate` | date-time | Yes | Date and time when the system was activated | +| `storageType` | enum | No | `LithiumIon`, `LeadAcid`, `FlowBattery`, or `Other` | + +## idRef + +A reusable identity reference pattern. In this credential it appears in: + +- **`issuer.idRef`** — the utility's regulatory registration +- **`customerProfile.idRef`** — the customer's external identity + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `issuedBy` | URI (DID) | Yes | DID of the authority that issued the identity | +| `subjectId` | string | Yes | Identifier in the format `authority-domain:id-value` | + +Example (customer's government ID): +```json +"idRef": { + "issuedBy": "did:web:ssa.gov", + "subjectId": "ssa.gov:XXX-XX-1234" +} +``` + +## Files + +| File | Description | +|------|-------------| +| `context.jsonld` | JSON-LD context defining semantic mappings for all five profile sections | +| `schema.json` | JSON Schema (draft 2020-12) for credential validation | +| `example.json` | Sample credential with all five profiles populated | diff --git a/specification/energy-credentials/electricity-credential/schema.json b/specification/energy-credentials/electricity-credential/schema.json new file mode 100644 index 00000000..7cbb55e6 --- /dev/null +++ b/specification/energy-credentials/electricity-credential/schema.json @@ -0,0 +1,576 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/beckn/DEG/blob/main/specification/energy-credentials/electricity-credential/schema.json", + "title": "Customer Credential Schema", + "description": "JSON Schema for a unified customer credential that combines customer identity, customer details, consumption characteristics, generation capability, and storage capability as equal-level properties within a single W3C Verifiable Credential (VC Data Model 2.0). Issued by energy providers.", + "type": "object", + "required": [ + "@context", + "id", + "type", + "issuer", + "validFrom", + "credentialSubject" + ], + "properties": { + "@context": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "https://www.w3.org/ns/credentials/v2" + }, + "minItems": 2 + }, + "id": { + "type": "string", + "format": "uri", + "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", + "description": "Unique identifier for the credential in URN UUID format" + }, + "type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "CustomerCredential" + }, + "minItems": 2 + }, + "issuer": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of the issuing provider" + }, + "name": { + "type": "string", + "minLength": 1, + "description": "Name of the provider" + }, + "idRef": { + "type": "object", + "description": "Reference to an identity issued by an external authority", + "required": [ + "issuedBy", + "subjectId" + ], + "properties": { + "issuedBy": { + "type": "string", + "format": "uri", + "description": "DID of the authority that issued the identity (e.g., did:web:kerc.karnataka.gov.in)" + }, + "subjectId": { + "type": "string", + "pattern": "^[A-Za-z0-9._-]+:[A-Za-z0-9X_-]+$", + "description": "Subject identifier in the format authority-domain:id-value (e.g., kerc.karnataka.gov.in:AABPC12345)" + } + } + } + } + }, + "validFrom": { + "type": "string", + "format": "date-time", + "description": "Date and time from which the credential is valid (W3C VC Data Model 2.0)" + }, + "validUntil": { + "type": "string", + "format": "date-time", + "description": "Date and time until which the credential is valid (W3C VC Data Model 2.0)" + }, + "credentialStatus": { + "type": "object", + "required": [ + "id", + "type", + "statusPurpose", + "statusListCredential" + ], + "description": "Revocation status information for the credential", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL to look up the revocation status of this specific credential via DeDi registry" + }, + "type": { + "type": "string", + "const": "dedi", + "description": "Type of status check mechanism (DeDi)" + }, + "statusPurpose": { + "type": "string", + "enum": [ + "revocation", + "suspension" + ], + "description": "Purpose of the credential status entry" + }, + "statusListCredential": { + "type": "string", + "format": "uri", + "description": "URL to the issuer revocation registry on DeDi" + } + } + }, + "credentialSubject": { + "type": "object", + "description": "Single subject with five profile sections: customerProfile (required), customerDetails, consumptionProfile, generationProfile, storageProfile (all optional except customerProfile)", + "required": [ + "customerProfile" + ], + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "Optional DID of the customer/credential subject" + }, + "customerProfile": { + "$ref": "#/$defs/CustomerProfile" + }, + "customerDetails": { + "$ref": "#/$defs/CustomerDetails" + }, + "consumptionProfile": { + "$ref": "#/$defs/ConsumptionProfile" + }, + "generationProfile": { + "$ref": "#/$defs/GenerationProfile" + }, + "storageProfile": { + "$ref": "#/$defs/StorageProfile" + } + } + }, + "proof": { + "type": "object", + "required": [ + "type", + "created", + "verificationMethod", + "proofPurpose", + "proofValue" + ], + "properties": { + "type": { + "type": "string", + "description": "Cryptographic signature type (e.g., Ed25519Signature2020)" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the proof was created" + }, + "verificationMethod": { + "type": "string", + "format": "uri", + "description": "URI of the verification method/public key" + }, + "proofPurpose": { + "type": "string", + "enum": [ + "assertionMethod", + "authentication" + ], + "description": "Purpose of the proof" + }, + "proofValue": { + "type": "string", + "minLength": 1, + "description": "The cryptographic signature value" + } + } + } + }, + "$defs": { + "CustomerProfile": { + "type": "object", + "description": "Core customer identity: customer number, meter number, external ID reference", + "required": [ + "customerNumber", + "meterNumber", + "meterType" + ], + "properties": { + "customerNumber": { + "type": "string", + "minLength": 1, + "description": "Full customer account number assigned by the utility" + }, + "meterNumber": { + "type": "string", + "minLength": 1, + "maxLength": 50, + "description": "Unique meter serial number" + }, + "meterType": { + "type": "string", + "description": "Type of electricity meter installed. Values derived from Green Button / ESPI meter kind classifications.", + "enum": [ + "AMR", + "AMI", + "Electromechanical", + "Forward", + "Reverse", + "Bidirectional", + "Prepaid", + "NetMeter", + "Other" + ] + }, + "idRef": { + "type": "object", + "description": "Reference to an identity issued by an external authority", + "required": [ + "issuedBy", + "subjectId" + ], + "properties": { + "issuedBy": { + "type": "string", + "format": "uri", + "description": "DID of the authority that issued the identity (e.g., did:web:kerc.karnataka.gov.in)" + }, + "subjectId": { + "type": "string", + "pattern": "^[A-Za-z0-9._-]+:[A-Za-z0-9X_-]+$", + "description": "Subject identifier in the format authority-domain:id-value (e.g., kerc.karnataka.gov.in:AABPC12345)" + } + } + } + } + }, + "CustomerDetails": { + "type": "object", + "description": "Customer personal and address information", + "required": [ + "fullName", + "installationAddress", + "serviceConnectionDate" + ], + "properties": { + "fullName": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "Full name of the customer as per ID proof" + }, + "installationAddress": { + "type": "object", + "description": "The physical location of the installation. Follows the beckn Location schema.", + "required": [ + "address", + "area_code", + "country" + ], + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the location" + }, + "descriptor": { + "type": "object", + "description": "Physical description of the location", + "properties": { + "name": { + "type": "string", + "description": "Name of the location" + }, + "code": { + "type": "string", + "description": "Location code" + }, + "short_desc": { + "type": "string", + "description": "Short description of the location" + }, + "long_desc": { + "type": "string", + "description": "Long description of the location" + } + } + }, + "map_url": { + "type": "string", + "format": "uri", + "description": "URL to the map of the location" + }, + "gps": { + "type": "string", + "pattern": "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$", + "description": "GPS coordinates of the installation (e.g., '12.9716,77.5946')" + }, + "address": { + "type": "string", + "minLength": 1, + "description": "Complete postal address of the installation" + }, + "city": { + "type": "object", + "description": "City of the installation", + "properties": { + "name": { + "type": "string", + "description": "Name of the city" + }, + "code": { + "type": "string", + "description": "City code" + } + } + }, + "district": { + "type": "string", + "description": "District or county name" + }, + "state": { + "type": "object", + "description": "State or province of the installation", + "properties": { + "name": { + "type": "string", + "description": "Name of the state" + }, + "code": { + "type": "string", + "description": "State code as per country or international standards" + } + } + }, + "country": { + "type": "object", + "description": "Country of the installation", + "required": [ + "code" + ], + "properties": { + "name": { + "type": "string", + "description": "Name of the country" + }, + "code": { + "type": "string", + "pattern": "^[A-Z]{2}$", + "description": "Country code as per ISO 3166-1 alpha-2 format" + } + } + }, + "area_code": { + "type": "string", + "minLength": 1, + "description": "Area code or postal/ZIP code" + }, + "circle": { + "type": "object", + "description": "Circular geo-fence around the location", + "properties": { + "gps": { + "type": "string", + "pattern": "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$", + "description": "GPS coordinates of the center" + }, + "radius": { + "type": "object", + "description": "Radius of the circle", + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + }, + "estimated_value": { + "type": "string" + }, + "computed_value": { + "type": "string" + }, + "range": { + "type": "object", + "properties": { + "min": { + "type": "string" + }, + "max": { + "type": "string" + } + } + }, + "unit": { + "type": "string" + } + } + } + } + }, + "polygon": { + "type": "string", + "description": "Boundary polygon of the location" + }, + "3dspace": { + "type": "string", + "description": "Three dimensional region describing the location" + }, + "rating": { + "type": "string", + "description": "Rating of the location" + }, + "openLocationCode": { + "type": "string", + "pattern": "^[23456789CFGHJMPQRVWX]{4,8}\\+[23456789CFGHJMPQRVWX]{0,4}$", + "description": "Open Location Code (OLC) for the installation location" + } + } + }, + "serviceConnectionDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when the electricity connection was activated (with timezone offset)" + } + } + }, + "ConsumptionProfile": { + "type": "object", + "description": "Connection and consumption characteristics for load management and tariff purposes", + "required": [ + "premisesType", + "connectionType", + "sanctionedLoadKW", + "tariffCategoryCode" + ], + "properties": { + "premisesType": { + "type": "string", + "enum": [ + "Residential", + "Commercial", + "Industrial", + "Agricultural" + ], + "description": "Type of premises for the electricity connection" + }, + "connectionType": { + "type": "string", + "enum": [ + "Single-phase", + "Three-phase" + ], + "description": "Type of electrical connection" + }, + "sanctionedLoadKW": { + "type": "number", + "minimum": 0.5, + "maximum": 10000, + "description": "Sanctioned/approved electrical load in kilowatts (kW)" + }, + "tariffCategoryCode": { + "type": "string", + "minLength": 1, + "description": "Billing/tariff category code assigned by the utility" + } + } + }, + "GenerationProfile": { + "type": "object", + "description": "DER (Distributed Energy Resource) generation capability", + "required": [ + "generationType", + "capacityKW", + "commissioningDate" + ], + "properties": { + "assetId": { + "type": "string", + "minLength": 1, + "description": "Unique identifier for the generation asset" + }, + "generationType": { + "type": "string", + "enum": [ + "Solar", + "Wind", + "MicroHydro", + "Other" + ], + "description": "Type of distributed energy generation" + }, + "capacityKW": { + "type": "number", + "minimum": 0.1, + "maximum": 10000, + "description": "Installed generation capacity in kilowatts (kW)" + }, + "commissioningDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when the generation system was activated (with timezone offset)" + }, + "manufacturer": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "Equipment manufacturer" + }, + "modelNumber": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "description": "Equipment model number" + } + } + }, + "StorageProfile": { + "type": "object", + "description": "Battery/energy storage capability", + "required": [ + "storageCapacityKWh", + "powerRatingKW", + "commissioningDate" + ], + "properties": { + "assetId": { + "type": "string", + "minLength": 1, + "description": "Unique identifier for the storage asset" + }, + "storageCapacityKWh": { + "type": "number", + "minimum": 0.1, + "maximum": 10000, + "description": "Battery storage capacity in kilowatt-hours (kWh)" + }, + "powerRatingKW": { + "type": "number", + "minimum": 0.1, + "maximum": 10000, + "description": "Battery charge/discharge power rating in kilowatts (kW)" + }, + "commissioningDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when the storage system was activated (with timezone offset)" + }, + "storageType": { + "type": "string", + "enum": [ + "LithiumIon", + "LeadAcid", + "FlowBattery", + "Other" + ], + "description": "Type of battery storage technology" + } + } + } + } +} diff --git a/specification/energy-credentials/consumption-profile-vc/context.jsonld b/specification/energy-credentials/eos-schemas/consumption-profile-vc/context.jsonld similarity index 100% rename from specification/energy-credentials/consumption-profile-vc/context.jsonld rename to specification/energy-credentials/eos-schemas/consumption-profile-vc/context.jsonld diff --git a/specification/energy-credentials/consumption-profile-vc/example.json b/specification/energy-credentials/eos-schemas/consumption-profile-vc/example.json similarity index 100% rename from specification/energy-credentials/consumption-profile-vc/example.json rename to specification/energy-credentials/eos-schemas/consumption-profile-vc/example.json diff --git a/specification/energy-credentials/consumption-profile-vc/readme.md b/specification/energy-credentials/eos-schemas/consumption-profile-vc/readme.md similarity index 100% rename from specification/energy-credentials/consumption-profile-vc/readme.md rename to specification/energy-credentials/eos-schemas/consumption-profile-vc/readme.md diff --git a/specification/energy-credentials/consumption-profile-vc/schema.json b/specification/energy-credentials/eos-schemas/consumption-profile-vc/schema.json similarity index 100% rename from specification/energy-credentials/consumption-profile-vc/schema.json rename to specification/energy-credentials/eos-schemas/consumption-profile-vc/schema.json diff --git a/specification/energy-credentials/examples/consumption-profile-vc.json b/specification/energy-credentials/eos-schemas/examples/consumption-profile-vc.json similarity index 100% rename from specification/energy-credentials/examples/consumption-profile-vc.json rename to specification/energy-credentials/eos-schemas/examples/consumption-profile-vc.json diff --git a/specification/energy-credentials/examples/generation-profile-vc.json b/specification/energy-credentials/eos-schemas/examples/generation-profile-vc.json similarity index 100% rename from specification/energy-credentials/examples/generation-profile-vc.json rename to specification/energy-credentials/eos-schemas/examples/generation-profile-vc.json diff --git a/specification/energy-credentials/examples/storage-profile-vc.json b/specification/energy-credentials/eos-schemas/examples/storage-profile-vc.json similarity index 100% rename from specification/energy-credentials/examples/storage-profile-vc.json rename to specification/energy-credentials/eos-schemas/examples/storage-profile-vc.json diff --git a/specification/energy-credentials/examples/utility-customer-vc. json b/specification/energy-credentials/eos-schemas/examples/utility-customer-vc. json similarity index 100% rename from specification/energy-credentials/examples/utility-customer-vc. json rename to specification/energy-credentials/eos-schemas/examples/utility-customer-vc. json diff --git a/specification/energy-credentials/generation-profile-vc/context.jsonld b/specification/energy-credentials/eos-schemas/generation-profile-vc/context.jsonld similarity index 100% rename from specification/energy-credentials/generation-profile-vc/context.jsonld rename to specification/energy-credentials/eos-schemas/generation-profile-vc/context.jsonld diff --git a/specification/energy-credentials/generation-profile-vc/example.json b/specification/energy-credentials/eos-schemas/generation-profile-vc/example.json similarity index 100% rename from specification/energy-credentials/generation-profile-vc/example.json rename to specification/energy-credentials/eos-schemas/generation-profile-vc/example.json diff --git a/specification/energy-credentials/generation-profile-vc/readme.md b/specification/energy-credentials/eos-schemas/generation-profile-vc/readme.md similarity index 100% rename from specification/energy-credentials/generation-profile-vc/readme.md rename to specification/energy-credentials/eos-schemas/generation-profile-vc/readme.md diff --git a/specification/energy-credentials/generation-profile-vc/schema.json b/specification/energy-credentials/eos-schemas/generation-profile-vc/schema.json similarity index 100% rename from specification/energy-credentials/generation-profile-vc/schema.json rename to specification/energy-credentials/eos-schemas/generation-profile-vc/schema.json diff --git a/specification/energy-credentials/storage-profile-vc/context.jsonld b/specification/energy-credentials/eos-schemas/storage-profile-vc/context.jsonld similarity index 100% rename from specification/energy-credentials/storage-profile-vc/context.jsonld rename to specification/energy-credentials/eos-schemas/storage-profile-vc/context.jsonld diff --git a/specification/energy-credentials/storage-profile-vc/example.json b/specification/energy-credentials/eos-schemas/storage-profile-vc/example.json similarity index 100% rename from specification/energy-credentials/storage-profile-vc/example.json rename to specification/energy-credentials/eos-schemas/storage-profile-vc/example.json diff --git a/specification/energy-credentials/storage-profile-vc/readme.md b/specification/energy-credentials/eos-schemas/storage-profile-vc/readme.md similarity index 100% rename from specification/energy-credentials/storage-profile-vc/readme.md rename to specification/energy-credentials/eos-schemas/storage-profile-vc/readme.md diff --git a/specification/energy-credentials/storage-profile-vc/schema.json b/specification/energy-credentials/eos-schemas/storage-profile-vc/schema.json similarity index 100% rename from specification/energy-credentials/storage-profile-vc/schema.json rename to specification/energy-credentials/eos-schemas/storage-profile-vc/schema.json diff --git a/specification/energy-credentials/utility-customer-vc/context.jsonld b/specification/energy-credentials/eos-schemas/utility-customer-vc/context.jsonld similarity index 100% rename from specification/energy-credentials/utility-customer-vc/context.jsonld rename to specification/energy-credentials/eos-schemas/utility-customer-vc/context.jsonld diff --git a/specification/energy-credentials/utility-customer-vc/example.json b/specification/energy-credentials/eos-schemas/utility-customer-vc/example.json similarity index 100% rename from specification/energy-credentials/utility-customer-vc/example.json rename to specification/energy-credentials/eos-schemas/utility-customer-vc/example.json diff --git a/specification/energy-credentials/utility-customer-vc/readme.md b/specification/energy-credentials/eos-schemas/utility-customer-vc/readme.md similarity index 100% rename from specification/energy-credentials/utility-customer-vc/readme.md rename to specification/energy-credentials/eos-schemas/utility-customer-vc/readme.md diff --git a/specification/energy-credentials/utility-customer-vc/schema.json b/specification/energy-credentials/eos-schemas/utility-customer-vc/schema.json similarity index 100% rename from specification/energy-credentials/utility-customer-vc/schema.json rename to specification/energy-credentials/eos-schemas/utility-customer-vc/schema.json diff --git a/specification/energy-credentials/examples/program-enrollment-vc.json b/specification/energy-credentials/examples/program-enrollment-vc.json deleted file mode 100644 index d9608304..00000000 --- a/specification/energy-credentials/examples/program-enrollment-vc.json +++ /dev/null @@ -1,23 +0,0 @@ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://schema.org/", - "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/context.jsonld" - ], - "id": "urn:uuid:7f8e9d0c-5678-1234-abcd-123456789abc", - "type": ["VerifiableCredential", "UtilityProgramEnrollmentCredential"], - "issuer": { - "id": "did:web:bescom.karnataka.gov.in", - "name": "BESCOM - Bangalore Electricity Supply Company", - "licenseNumber": "KERC/DL/BESCOM/2024" - }, - "issuanceDate": "2025-01-15T11:00:00Z", - "credentialSubject": { - "id": "did:example:consumer:priya123", - "consumerNumber": "BESCOM-2025-MR4-567890", - "fullName": "Priya Sharma", - "programName": "BESCOM Surya Raitha - Rooftop Solar Net Metering", - "programCode": "SRTPV-NM-2025", - "enrollmentDate": "2025-01-15" - } - } diff --git a/specification/energy-credentials/program-enrollment-vc/context.jsonld b/specification/energy-credentials/program-enrollment-vc/context.jsonld index 2b42fa81..9b562592 100644 --- a/specification/energy-credentials/program-enrollment-vc/context.jsonld +++ b/specification/energy-credentials/program-enrollment-vc/context.jsonld @@ -6,58 +6,157 @@ "type": "@type", "schema": "https://schema.org/", "xsd": "http://www.w3.org/2001/XMLSchema#", - "utility": "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/context.jsonld#", - + "deg": "https://schema.beckn.io/deg#", "UtilityProgramEnrollmentCredential": { - "@id": "utility:UtilityProgramEnrollmentCredential", + "@id": "deg:UtilityProgramEnrollmentCredential", "@context": { "@version": 1.1, "@protected": true, "id": "@id", - "type": "@type", - "consumerNumber": { - "@id": "utility:consumerNumber", - "@type": "xsd:string" - }, - "fullName": { - "@id": "schema:name", + "type": "@type" + } + }, + "customerProfile": { + "@id": "deg:customerProfile", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + "customerNumber": { + "@id": "deg:customerNumber", "@type": "xsd:string" }, - "programName": { - "@id": "utility:programName", + "meterNumber": { + "@id": "deg:meterNumber", "@type": "xsd:string" }, - "programCode": { - "@id": "utility:programCode", + "meterType": { + "@id": "deg:meterType", "@type": "xsd:string" }, - "enrollmentDate": { - "@id": "utility:enrollmentDate", - "@type": "xsd:date" - }, - "validUntil": { - "@id": "utility:validUntil", - "@type": "xsd:date" + "idRef": { + "@id": "deg:idRef", + "@type": "@id", + "@context": { + "issuedBy": { + "@id": "deg:issuedBy", + "@type": "@id" + }, + "subjectId": { + "@id": "deg:subjectId", + "@type": "xsd:string" + } + } } } }, - - "UtilityIssuer": { - "@id": "utility:UtilityIssuer", + "customerDetails": { + "@id": "deg:customerDetails", + "@type": "@id", "@context": { "@version": 1.1, "@protected": true, - "id": "@id", - "type": "@type", - "name": { + "fullName": { "@id": "schema:name", "@type": "xsd:string" }, - "licenseNumber": { - "@id": "utility:licenseNumber", + "serviceConnectionDate": { + "@id": "deg:serviceConnectionDate", + "@type": "xsd:dateTime" + }, + "installationAddress": { + "@id": "deg:installationAddress", + "@type": "@id", + "@context": { + "fullAddress": { + "@id": "schema:streetAddress", + "@type": "xsd:string" + }, + "city": { + "@id": "schema:addressLocality", + "@type": "xsd:string" + }, + "district": { + "@id": "deg:district", + "@type": "xsd:string" + }, + "stateProvince": { + "@id": "schema:addressRegion", + "@type": "xsd:string" + }, + "postalCode": { + "@id": "schema:postalCode", + "@type": "xsd:string" + }, + "country": { + "@id": "schema:addressCountry", + "@type": "xsd:string" + }, + "geo": { + "@id": "schema:geo", + "@type": "@id", + "@context": { + "latitude": { + "@id": "schema:latitude", + "@type": "xsd:decimal" + }, + "longitude": { + "@id": "schema:longitude", + "@type": "xsd:decimal" + } + } + }, + "openLocationCode": { + "@id": "deg:openLocationCode", + "@type": "xsd:string" + } + } + } + } + }, + "programName": { + "@id": "deg:programName", + "@type": "xsd:string" + }, + "programCode": { + "@id": "deg:programCode", + "@type": "xsd:string" + }, + "enrollmentDate": { + "@id": "deg:enrollmentDate", + "@type": "xsd:dateTime" + }, + "enrollmentValidUntil": { + "@id": "deg:enrollmentValidUntil", + "@type": "xsd:dateTime" + }, + "idRef": { + "@id": "deg:idRef", + "@type": "@id", + "@context": { + "issuedBy": { + "@id": "deg:issuedBy", + "@type": "@id" + }, + "subjectId": { + "@id": "deg:subjectId", "@type": "xsd:string" } } + }, + "credentialStatus": { + "@id": "deg:credentialStatus", + "@type": "@id", + "@context": { + "statusPurpose": { + "@id": "deg:statusPurpose", + "@type": "xsd:string" + }, + "statusListCredential": { + "@id": "deg:statusListCredential", + "@type": "@id" + } + } } } } diff --git a/specification/energy-credentials/program-enrollment-vc/example.json b/specification/energy-credentials/program-enrollment-vc/example.json index 440ea9af..e84945df 100644 --- a/specification/energy-credentials/program-enrollment-vc/example.json +++ b/specification/energy-credentials/program-enrollment-vc/example.json @@ -1,33 +1,49 @@ { "@context": [ - "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/ns/credentials/v2", "https://schema.org/", - "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/context.jsonld" + "https://schema.beckn.io/programEnrollment", + "https://schema.beckn.io/customerProfile", + "https://schema.beckn.io/customerDetails" ], "id": "urn:uuid:7f8e9d0c-5678-1234-abcd-123456789abc", - "type": ["VerifiableCredential", "UtilityProgramEnrollmentCredential"], + "type": [ + "VerifiableCredential", + "UtilityProgramEnrollmentCredential" + ], "issuer": { - "id": "did:web:example-utility.com", + "id": "https://example-utility.com/issuers/energy-dept", "name": "Example Energy Utility", - "licenseNumber": "REG-2025-00001" + "idRef": { + "issuedBy": "did:web:exreg.gov", + "subjectId": "exreg.gov:AABPC00001" + } }, - "issuanceDate": "2025-01-13T11:00:00Z", + "validFrom": "2025-01-13T11:00:00-05:00", + "validUntil": "2026-01-13T11:00:00-05:00", "credentialStatus": { - "id": "https://dedi.global/dedi/query/did:web:example-utility.com/VC_revocation_registry", - "type": "dediregistry" + "id": "https://dedi.global/dedi/lookup/example-utility.com/vc-revocation-registry/7f8e9d0c-5678-1234-abcd-123456789abc", + "type": "dedi", + "statusPurpose": "revocation", + "statusListCredential": "https://dedi.global/dedi/query/example-utility.com/vc-revocation-registry" }, "credentialSubject": { - "id": "did:example:consumer:abc123", - "consumerNumber": "UTIL-2025-001234567", - "fullName": "Jane Doe", + "id": "did:example:customer:abc123", + "customerProfile": { + "customerNumber": "UTIL-2025-001234567" + }, + "customerDetails": { + "fullName": "Jane Doe" + }, "programName": "Peer-to-Peer Energy Trading", "programCode": "P2P-2025", - "enrollmentDate": "2025-01-13" + "enrollmentDate": "2025-01-13T00:00:00-05:00", + "enrollmentValidUntil": "2026-01-13T00:00:00-05:00" }, "proof": { "type": "Ed25519Signature2020", - "created": "2025-01-13T11:00:00Z", - "verificationMethod": "did:web:example-utility.com#key-1", + "created": "2025-01-13T11:00:00-05:00", + "verificationMethod": "https://example-utility.com/issuers/energy-dept#key-1", "proofPurpose": "assertionMethod", "proofValue": "z3FXQehWgc9VfTh8WpLmkJd2rNn..." } diff --git a/specification/energy-credentials/program-enrollment-vc/readme.md b/specification/energy-credentials/program-enrollment-vc/readme.md index 24d92a1d..fafd4538 100644 --- a/specification/energy-credentials/program-enrollment-vc/readme.md +++ b/specification/energy-credentials/program-enrollment-vc/readme.md @@ -1,6 +1,6 @@ # Utility Program Enrollment Credential -This credential is issued by electricity distribution utilities when a consumer enrolls in an energy program. Programs can include peer-to-peer trading, demand flexibility, virtual power plants, and other grid services. +This credential is issued by energy providers when a consumer enrolls in an energy program. Programs can include peer-to-peer trading, demand flexibility, virtual power plants, and other grid services. ## Use Cases @@ -10,49 +10,78 @@ This credential is issued by electricity distribution utilities when a consumer - **Time of Use**: Consumer opts into time-based pricing programs - **Net Metering**: Consumer is enrolled in net metering for solar exports -## Fields +## Credential Structure -| Field | Description | Required | -| :---- | :---- | :----: | -| consumerNumber | Unique consumer account number | Yes | -| fullName | Consumer name | No | -| programName | Human-readable program name | Yes | -| programCode | Unique program identifier | Yes | -| enrollmentDate | Date of enrollment | Yes | -| validUntil | End date when enrollment expires | No | +``` +credentialSubject +├── id (optional customer DID) +├── customerProfile (optional: customer number, meter, idRef) +├── customerDetails (optional: name, address, connection date) +├── programName (required) +├── programCode (required) +├── enrollmentDate (required) +└── enrollmentValidUntil (optional) +``` -## Files +## Issuer -- `schema.json` - JSON Schema for validation -- `context.jsonld` - JSON-LD context for semantic interoperability -- `example.json` - Sample P2P trading enrollment credential - -## Usage - -```json -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://schema.org/", - "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/context.jsonld" - ], - "type": ["VerifiableCredential", "UtilityProgramEnrollmentCredential"], - "credentialSubject": { - "id": "did:example:consumer:abc123", - "consumerNumber": "UTIL-2025-001234567", - "programName": "Peer-to-Peer Energy Trading", - "programCode": "P2P-2025", - "enrollmentDate": "2025-01-13" - } -} -``` +The credential is issued by energy providers. The issuer object contains: -Context URL: -``` -https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/context.jsonld -``` +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | URI | Yes | DID or URL of the issuing provider | +| `name` | string | Yes | Name of the provider | +| `idRef` | object | No | Regulatory identity reference — see [idRef](../electricity-credential/readme.md#idref) | -Schema URL: -``` -https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/schema.json -``` +## Validity Period + +Per the [W3C VC Data Model 2.0 validity period](https://www.w3.org/TR/2025/REC-vc-data-model-2.0-20250515/#validity-period), this credential uses: + +- **`validFrom`** (required) — date-time from which the credential is valid +- **`validUntil`** (optional) — date-time until which the credential is valid + +All date-time values include an explicit timezone offset (e.g., `2025-01-13T11:00:00-05:00`). + +## Revocation + +Credential revocation is managed via DeDi. See [credentialStatus](../readme.md#credentialstatus) in the top-level readme. + +## Profile Sections + +### customerProfile (optional) + +Core customer identity fields — same structure as [Customer Credential](../electricity-credential/readme.md#customerprofile): + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `customerNumber` | string | Yes | Full customer account number assigned by the utility | +| `meterNumber` | string | No | Unique meter serial number | +| `meterType` | enum | No | Type of meter — see [meterType enum](../electricity-credential/readme.md#metertype-enum) | +| `idRef` | object | No | External identity reference — see [idRef](../electricity-credential/readme.md#idref) | + +### customerDetails (optional) + +Personal and address information — same structure as [Customer Credential](../electricity-credential/readme.md#customerdetails): + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `fullName` | string | Yes | Full name of the customer as per ID proof | +| `installationAddress` | object | No | Address of the installation (includes optional `geo` and `openLocationCode`) | +| `serviceConnectionDate` | date-time | No | Date and time when the electricity connection was activated | + +### Enrollment Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `programName` | string | Yes | Human-readable program name | +| `programCode` | string | Yes | Unique program identifier | +| `enrollmentDate` | date-time | Yes | Date and time of enrollment | +| `enrollmentValidUntil` | date-time | No | End date and time when enrollment expires | + +## Files + +| File | Description | +|------|-------------| +| `context.jsonld` | JSON-LD context defining semantic mappings | +| `schema.json` | JSON Schema (draft 2020-12) for credential validation | +| `example.json` | Sample P2P trading enrollment credential | diff --git a/specification/energy-credentials/program-enrollment-vc/schema.json b/specification/energy-credentials/program-enrollment-vc/schema.json index e8248343..aba53063 100644 --- a/specification/energy-credentials/program-enrollment-vc/schema.json +++ b/specification/energy-credentials/program-enrollment-vc/schema.json @@ -1,15 +1,15 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://nfh-trust-labs.github.io/vc-schemas/energy-credentials/program-enrollment-vc/schema.json", + "$id": "https://github.com/beckn/DEG/blob/main/specification/energy-credentials/program-enrollment-vc/schema.json", "title": "Utility Program Enrollment Credential Schema", - "description": "JSON Schema for verifying Program Enrollment Credentials issued by electricity distribution utilities when consumers enroll in programs like P2P trading, demand flexibility, virtual power plants, etc.", + "description": "JSON Schema for verifying Program Enrollment Credentials issued by energy providers when consumers enroll in programs like P2P trading, demand flexibility, virtual power plants, etc.", "type": "object", "required": [ "@context", "id", "type", "issuer", - "issuanceDate", + "validFrom", "credentialSubject" ], "properties": { @@ -19,7 +19,7 @@ "type": "string" }, "contains": { - "const": "https://www.w3.org/2018/credentials/v1" + "const": "https://www.w3.org/ns/credentials/v2" }, "minItems": 2 }, @@ -41,57 +41,91 @@ }, "issuer": { "type": "object", - "required": ["id", "name", "licenseNumber"], + "required": [ + "id", + "name" + ], "properties": { "id": { "type": "string", "format": "uri", - "description": "DID of the issuing distribution utility" + "description": "URL of the issuing provider" }, "name": { "type": "string", "minLength": 1, - "description": "Name of the distribution utility" + "description": "Name of the provider" }, - "licenseNumber": { - "type": "string", - "minLength": 1, - "description": "Regulatory license number issued by the local energy regulator" + "idRef": { + "type": "object", + "description": "Reference to an identity issued by an external authority", + "required": [ + "issuedBy", + "subjectId" + ], + "properties": { + "issuedBy": { + "type": "string", + "format": "uri", + "description": "DID of the authority that issued the identity (e.g., did:web:kerc.karnataka.gov.in)" + }, + "subjectId": { + "type": "string", + "pattern": "^[A-Za-z0-9._-]+:[A-Za-z0-9X_-]+$", + "description": "Subject identifier in the format authority-domain:id-value (e.g., kerc.karnataka.gov.in:AABPC12345)" + } + } } } }, - "issuanceDate": { + "validFrom": { "type": "string", "format": "date-time", - "description": "Date and time when the credential was issued" + "description": "Date and time from which the credential is valid (W3C VC Data Model 2.0)" }, - "expirationDate": { + "validUntil": { "type": "string", "format": "date-time", - "description": "Optional expiration date of the credential" + "description": "Date and time until which the credential is valid (W3C VC Data Model 2.0)" }, "credentialStatus": { "type": "object", - "required": ["id", "type"], + "required": [ + "id", + "type", + "statusPurpose", + "statusListCredential" + ], "description": "Revocation status information for the credential", "properties": { "id": { "type": "string", "format": "uri", - "description": "URL to query the revocation status of the credential via DeDi registry" + "description": "URL to look up the revocation status of this specific credential via DeDi registry" }, "type": { "type": "string", - "const": "dediregistry", - "description": "Type of status check mechanism (DeDi Registry)" + "const": "dedi", + "description": "Type of status check mechanism (DeDi)" + }, + "statusPurpose": { + "type": "string", + "enum": [ + "revocation", + "suspension" + ], + "description": "Purpose of the credential status entry" + }, + "statusListCredential": { + "type": "string", + "format": "uri", + "description": "URL to the issuer revocation registry on DeDi" } } }, "credentialSubject": { "type": "object", "required": [ - "id", - "consumerNumber", "programName", "programCode", "enrollmentDate" @@ -100,18 +134,13 @@ "id": { "type": "string", "format": "uri", - "description": "DID of the consumer/credential subject" + "description": "Optional DID of the consumer/credential subject" }, - "consumerNumber": { - "type": "string", - "minLength": 1, - "description": "Unique consumer/customer account number assigned by the utility" + "customerProfile": { + "$ref": "#/$defs/CustomerProfile" }, - "fullName": { - "type": "string", - "minLength": 1, - "maxLength": 200, - "description": "Consumer name (optional)" + "customerDetails": { + "$ref": "#/$defs/CustomerDetails" }, "programName": { "type": "string", @@ -126,19 +155,25 @@ }, "enrollmentDate": { "type": "string", - "format": "date", - "description": "Date when the consumer enrolled in the program" + "format": "date-time", + "description": "Date and time when the consumer enrolled in the program (with timezone offset)" }, - "validUntil": { + "enrollmentValidUntil": { "type": "string", - "format": "date", - "description": "Optional end date when the enrollment expires" + "format": "date-time", + "description": "Optional end date and time when the enrollment expires (with timezone offset)" } } }, "proof": { "type": "object", - "required": ["type", "created", "verificationMethod", "proofPurpose", "proofValue"], + "required": [ + "type", + "created", + "verificationMethod", + "proofPurpose", + "proofValue" + ], "properties": { "type": { "type": "string", @@ -156,7 +191,10 @@ }, "proofPurpose": { "type": "string", - "enum": ["assertionMethod", "authentication"], + "enum": [ + "assertionMethod", + "authentication" + ], "description": "Purpose of the proof" }, "proofValue": { @@ -166,5 +204,150 @@ } } } + }, + "$defs": { + "CustomerProfile": { + "type": "object", + "description": "Core customer identity: customer number, meter number, external ID reference", + "required": [ + "customerNumber" + ], + "properties": { + "customerNumber": { + "type": "string", + "minLength": 1, + "description": "Full customer account number assigned by the utility" + }, + "meterNumber": { + "type": "string", + "minLength": 1, + "maxLength": 50, + "description": "Unique meter serial number" + }, + "meterType": { + "type": "string", + "description": "Type of electricity meter installed. Values derived from Green Button / ESPI meter kind classifications.", + "enum": [ + "AMR", + "AMI", + "Electromechanical", + "Forward", + "Reverse", + "Bidirectional", + "Prepaid", + "NetMeter", + "Other" + ] + }, + "idRef": { + "type": "object", + "description": "Reference to an identity issued by an external authority", + "required": [ + "issuedBy", + "subjectId" + ], + "properties": { + "issuedBy": { + "type": "string", + "format": "uri", + "description": "DID of the authority that issued the identity (e.g., did:web:kerc.karnataka.gov.in)" + }, + "subjectId": { + "type": "string", + "pattern": "^[A-Za-z0-9._-]+:[A-Za-z0-9X_-]+$", + "description": "Subject identifier in the format authority-domain:id-value (e.g., kerc.karnataka.gov.in:AABPC12345)" + } + } + } + } + }, + "CustomerDetails": { + "type": "object", + "description": "Customer personal and address information", + "required": [ + "fullName" + ], + "properties": { + "fullName": { + "type": "string", + "minLength": 1, + "maxLength": 200, + "description": "Full name of the customer as per ID proof" + }, + "installationAddress": { + "type": "object", + "required": [ + "fullAddress", + "postalCode", + "country" + ], + "properties": { + "fullAddress": { + "type": "string", + "minLength": 1, + "maxLength": 500, + "description": "Complete street address of the installation" + }, + "city": { + "type": "string", + "minLength": 1, + "description": "City name" + }, + "district": { + "type": "string", + "minLength": 1, + "description": "District or county name" + }, + "stateProvince": { + "type": "string", + "minLength": 1, + "description": "State, province, or region name" + }, + "postalCode": { + "type": "string", + "minLength": 1, + "description": "Postal or ZIP code (format varies by country)" + }, + "country": { + "type": "string", + "pattern": "^[A-Z]{2}$", + "description": "ISO 3166-1 alpha-2 country code" + }, + "geo": { + "type": "object", + "description": "Geographic coordinates of the installation", + "properties": { + "latitude": { + "type": "number", + "minimum": -90, + "maximum": 90, + "description": "Latitude in decimal degrees (WGS84)" + }, + "longitude": { + "type": "number", + "minimum": -180, + "maximum": 180, + "description": "Longitude in decimal degrees (WGS84)" + } + }, + "required": [ + "latitude", + "longitude" + ] + }, + "openLocationCode": { + "type": "string", + "pattern": "^[23456789CFGHJMPQRVWX]{4,8}\\+[23456789CFGHJMPQRVWX]{0,4}$", + "description": "Open Location Code (OLC) for the installation location" + } + } + }, + "serviceConnectionDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when the electricity connection was activated (with timezone offset)" + } + } + } } } diff --git a/specification/energy-credentials/readme.md b/specification/energy-credentials/readme.md index e84f39ef..d09a7858 100644 --- a/specification/energy-credentials/readme.md +++ b/specification/energy-credentials/readme.md @@ -4,99 +4,117 @@ Schemas for Verifiable Credentials in the energy sector. ## Overview -This collection provides schemas for credentials issued by electricity distribution utilities to consumers and prosumers. The credentials are designed to be modular and privacy-preserving, allowing for selective disclosure of customer information. +This collection provides schemas for credentials issued by energy providers to consumers and prosumers. The credentials are designed to be privacy-preserving and follow the W3C VC Data Model 2.0. ## Available Credentials | Credential | Description | Purpose | |------------|-------------|---------| -| [Utility Customer Credential](./utility-customer-vc/) | Barebones identity credential | Privacy-preserving customer identification | -| [Consumption Profile Credential](./consumption-profile-vc/) | Connection and load characteristics | Load management, tariff determination | -| [Generation Profile Credential](./generation-profile-vc/) | DER generation capability | Grid management, net metering, renewable tracking | -| [Storage Profile Credential](./storage-profile-vc/) | Battery/energy storage capability | Virtual power plants, demand response | -| [Program Enrollment Credential](./program-enrollment-vc/) | Energy program participation | Demand response, ToU programs | +| [Customer Credential](./electricity-credential/) | Unified credential combining customer identity, consumption, generation, and storage profiles | Single credential per meter for consumer/prosumer identity | +| [Program Enrollment Credential](./program-enrollment-vc/) | Energy program participation | P2P trading, demand response, virtual power plants, ToU programs | -## Credential Relationships +## Shared Data Objects +Both credentials share the same `customerProfile` and `customerDetails` object structures: + +- **customerProfile** — customer number, meter number, meter type, external identity reference (`idRef`) +- **customerDetails** — full name, installation address (with optional geo tagging and Open Location Code), service connection date + +In the Customer Credential these are required; in the Program Enrollment Credential they are optional. + +## Shared Patterns + +### idRef + +A reusable identity reference pattern used wherever one entity's identity is issued by another authority. It appears in two places: + +- **`issuer.idRef`** — the utility's regulatory registration (issued by the energy regulator) +- **`customerProfile.idRef`** — the customer's identity (issued by a government body or other authority) + +Structure: + +```json +"idRef": { + "issuedBy": "did:web:kerc.karnataka.gov.in", + "subjectId": "kerc.karnataka.gov.in:AABPC12345" +} ``` -┌─────────────────────────────┐ -│ Utility Customer Credential │ (Base identity - required) -│ - Masked consumer number │ -│ - Name, address, meter │ -└──────────────┬──────────────┘ - │ - │ Links via customer DID - ▼ -┌──────────────────────────────────────────────────────────────┐ -│ Optional Profile Credentials │ -├────────────────────┬─────────────────────┬───────────────────┤ -│ Consumption Profile│ Generation Profile │ Storage Profile │ -│ - Load/tariff info │ - Solar/Wind/etc. │ - Battery capacity│ -│ - Connection type │ - Capacity (kW) │ - Power rating │ -└────────────────────┴─────────────────────┴───────────────────┘ -``` -All profile credentials link to the customer via the `credentialSubject.id` field (customer DID). +| Field | Type | Description | +|-------|------|-------------| +| `issuedBy` | URI (DID) | DID of the authority that issued the identity | +| `subjectId` | string | Identifier in the format `authority-domain:id-value` | + +### credentialStatus -## Credential Issuance Scenarios +All credentials use the DeDi registry for revocation. The `credentialStatus` object contains: + +```json +"credentialStatus": { + "id": "https://dedi.global/dedi/lookup/{issuer-domain}/vc-revocation-registry/{credential-uuid}", + "type": "dedi", + "statusPurpose": "revocation", + "statusListCredential": "https://dedi.global/dedi/query/{issuer-domain}/vc-revocation-registry" +} +``` -### Pure Consumer -- **Has**: Utility Customer Credential, Consumption Profile Credential -- **Does not have**: Generation Profile, Storage Profile +| Field | Type | Description | +|-------|------|-------------| +| `id` | URI | Lookup URL for this specific credential's revocation status | +| `type` | string | Always `dedi` | +| `statusPurpose` | enum | `revocation` or `suspension` | +| `statusListCredential` | URI | URL to the issuer's revocation registry | -### Solar Prosumer -- **Has**: Utility Customer Credential, Consumption Profile, Generation Profile (Solar) -- **May have**: Storage Profile (if battery installed) +### DateTime Format -### Full Prosumer -- **Has**: All credential types -- **May have**: Multiple Generation Profiles (e.g., solar + wind) -- **May have**: Multiple Storage Profiles (e.g., home battery + EV) +All date and time fields use ISO 8601 `date-time` format with an explicit timezone offset (not UTC/GMT). This ensures unambiguous interpretation across jurisdictions. + +Example: `"2025-01-15T10:30:00+05:30"` (IST) or `"2025-01-13T10:30:00-05:00"` (EST) ## Directory Structure ``` energy-credentials/ -├── utility-customer-vc/ # Base identity credential -│ ├── schema.json -│ ├── context.jsonld -│ ├── example.json -│ └── readme.md -├── consumption-profile-vc/ # Connection/load characteristics -│ ├── schema.json -│ ├── context.jsonld -│ ├── example.json -│ └── readme.md -├── generation-profile-vc/ # DER generation capability +├── electricity-credential/ # Customer Credential (all profiles in one) │ ├── schema.json │ ├── context.jsonld │ ├── example.json │ └── readme.md -├── storage-profile-vc/ # Battery storage capability +├── program-enrollment-vc/ # Program participation │ ├── schema.json │ ├── context.jsonld │ ├── example.json │ └── readme.md -├── program-enrollment-vc/ # Program participation -│ ├── schema.json -│ ├── context.jsonld -│ ├── example.json -│ └── readme.md -└── readme.md # This file +├── eos-schemas/ # Archived: original per-profile schemas (pre-unification) +│ ├── consumption-profile-vc/ +│ ├── generation-profile-vc/ +│ ├── storage-profile-vc/ +│ ├── utility-customer-vc/ +│ └── examples/ +└── readme.md # This file ``` -## Privacy Considerations - -The modular design allows for selective disclosure: - -- **Utility Customer Credential** uses a masked consumer number to protect the full account number -- **Consumption Profile** can be shared for load management without revealing identity -- **Generation/Storage Profiles** enable participation in energy programs without exposing personal details - ## Schema Standards All schemas follow: -- W3C Verifiable Credentials Data Model 1.1 +- W3C Verifiable Credentials Data Model 2.0 - JSON-LD 1.1 for semantic interoperability - JSON Schema (draft 2020-12) for validation - Schema.org vocabulary where applicable + +## @context Resolution + +Each credential's `@context` array lists the W3C VC context, Schema.org, and individual `schema.beckn.io` URLs for each object type used: + +```json +"@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schema.org/", + "https://schema.beckn.io/customerCredential", + "https://schema.beckn.io/customerProfile", + "https://schema.beckn.io/customerDetails", + "https://schema.beckn.io/consumptionProfile", + "https://schema.beckn.io/generationProfile", + "https://schema.beckn.io/storageProfile" +] +```