services
The services/ packages provide the infrastructure adapters consumed by ABCI binaries and API servers. Each package defines an interface and one or more concrete implementations. Swap implementations by changing which concrete type is injected at startup — the ABCI state machines depend only on the interfaces.
Import root: github.com/ShywareLLC/core/services
services/identity
Defines IdentityVerifier — the interface the state machine uses to verify IDV attestations and derive identityHash.
type IdentityVerifier interface {
VerifyAndIdentify(data *tx.BallotCastData) (string, error)
VerifyAndIdentifyUpdate(data *tx.BallotUpdateData) (string, error)
VerifyAndIdentifyConfirm(data *tx.ConfirmReceiptData) (string, error)
}
Implementations
| Type | identity.provider | Notes |
|---|---|---|
DiditVerifier | didit | Document-scoped, enclave-attested identity; recovery requires a separate authenticated service |
IdentusVerifier | identus | DID wallet credential attestation |
WalletVerifier | wallet | ECDSA wallet-key commitment |
NoopVerifier | none | Dev/demo — skips verification, derives hash from pubkey |
ZKVerifier | didit (ZK tier) | Groth16 nullifier proof; current commitment is public |
KYB extension
KYBVerifier handles entity (business) verification alongside participant identity:
type KYBVerifier interface {
VerifyEntity(req *EntityVerificationRequest) (*EntityRecord, error)
}
PersonaVerifier implements KYBVerifier for Persona-based business identity workflows.
services/signer
Defines the Signer interface consumed by the protocol state machine and every concrete implementation below:
type Signer interface {
Sign(ctx context.Context, payload []byte) ([]byte, error)
PublicKeyDER() []byte
}
Using the interface rather than any one concrete type allows local software signers in development and test — and any of the four managed-HSM backends below — without changing ABCI app code.
Implementations
| Package | Backend | Constructor |
|---|---|---|
services/kms | AWS KMS | kms.NewSigner(ctx, keyID string) |
services/azure | Azure Key Vault | azure.NewSigner(ctx, opts ...Option) — WithKeyURI, or WithVaultName + WithKeyName (+ optional WithKeyVersion) |
services/gcp | Google Cloud KMS | gcp.NewSigner(ctx, keyName string, opts ...option.ClientOption) |
services/vault | HashiCorp Vault Transit | vault.NewSigner(ctx, opts ...Option) — WithAddr, WithToken, WithMount, WithKeyName |
All four expose the same Sign / PublicKeyDER / VerifyDER surface, so any one drops into the Signer interface unchanged. The key never leaves the managed boundary in any of them — signing happens inside KMS/Key Vault/Cloud KMS/Vault, not in the ABCI process.
Current wiring note: the reference shyvoting-abci binary constructs services/kms.Signer directly (--kms-key-id / signing.tally_key_id in the shyconfig) and does not yet expose a runtime switch across the other three. They're real, tested implementations of the same interface — using one today means building your own small main that constructs it and passes it where shyvoting-abci passes its KMS signer, not a drop-in environment variable. If your deployment needs Azure/GCP/Vault signing without a custom build, say so — that's a small addition to the reference binary, not a new interface.
services/reconcile
Off-chain linkage store for the reconciling authority's per-participant receipt store. Four built-in implementations; implement Store directly for any other backend.
type Store interface {
RecordSubmission(ctx context.Context, pollID, identityHash, submissionID string) error
GetSubmissionID(ctx context.Context, pollID, identityHash string) (string, error)
RevealBallotEvidence(ctx context.Context, pollID, identityHash string) (string, error)
DeleteSubmission(ctx context.Context, pollID, identityHash string) error
}
// Any Postgres-compatible DB (CockroachDB, pg, RDS, Aurora, Supabase, Neon, PlanetScale Postgres)
func NewPostgresStore(db *sql.DB) *PostgresStore
// MySQL-compatible DB (MySQL, MariaDB, TiDB, Aurora MySQL, PlanetScale MySQL)
func NewMySQLStore(db *sql.DB) *MySQLStore
// AWS DynamoDB — for Lambda + DynamoDB stacks where a Postgres instance is out of place
func NewDynamoDBStore(ctx context.Context) (*DynamoDBStore, error)
func NewDynamoDBStoreWithClient(client *dynamodb.Client, table string) *DynamoDBStore
// MongoDB-compatible DB (MongoDB Atlas, DocumentDB, Cosmos DB MongoDB API, FerretDB, etc.)
func NewMongoStore(ctx context.Context, opts ...MongoOption) (*MongoStore, *mongo.Client, error)
func NewMongoStoreWithCollection(coll *mongo.Collection) *MongoStore
// Cloud Firestore — for GCP operators already using Firebase auth + GCP KMS
// Document IDs are SHA-256(pollID || identityHash): opaque, non-enumerable by poll
func NewFirestoreStore(ctx context.Context, opts ...FirestoreOption) (*FirestoreStore, error)
func NewFirestoreStoreWithClient(client *firestore.Client, collection string) *FirestoreStore
// In-process map — zero dependencies, for unit tests and local dev
var store reconcile.MemoryStore // zero value is ready to use
No implementation exposes a global scan primitive — GetSubmissionID and RevealBallotEvidence are per-participant and identity-gated. DeleteSubmission is called on TxTypeAuthorityRescind (count-match embodiments only). Pass DATABASE_URL to SQL-backed binaries; the driver (pgx vs go-sql-driver/mysql) determines which SQL store to instantiate. DynamoDB reads AWS_REGION + DYNAMODB_RECEIPT_TABLE. MongoDB reads MONGODB_URI + MONGODB_DB + MONGODB_RECEIPT_COLLECTION.
When --db-url is empty at startup, the API server runs in write-only posture — reconcile calls are no-ops and participants receive no off-chain receipt.
services/attest
Server-side device attestation verification for write-only posture enforcement.
type Verifier interface {
Verify(ctx context.Context, token string) (*VerifiedAttestation, error)
}
type VerifiedAttestation struct {
Platform string // "android" | "ios"
AppID string
Trusted bool
Reason string
}
Implementations
| Type | Platform | Notes |
|---|---|---|
PlayIntegrityVerifier | Android | Verifies Google Play Integrity API tokens |
NopVerifier | Dev | Always returns Trusted: true |
PlayIntegrityVerifier is configured with PlayIntegrityConfig{PackageName, GoogleAppCredentials}. The API server calls Verify on each submission when deployment.runtime_fallbacks.write_only_on_missing_play_integrity: true — a failed or missing token triggers write-only posture for that submission.
services/telemetry
OpenTelemetry initialisation for all shyware server binaries.
func Init(ctx context.Context, serviceName string) (trace.TracerProvider, func(context.Context) error, error)
func Tracer(name string) trace.Tracer
Init sets up an OTLP trace exporter. The returned shutdown function flushes pending spans on graceful exit. Every ABCI binary and API server calls telemetry.Init at startup with its service name.
The service name appears as the service.name resource attribute in all traces — use it to filter spans in Grafana or the AWS X-Ray console. The SDK telemetry adapters (sdk/web/adapters/telemetry/) emit client-side spans that correlate with server-side traces via traceparent propagation.