// Specialized skill for nondominium Holochain DNA development, focusing on zome creation, entry patterns, integrity/coordinator architecture, ValueFlows compliance, and WASM optimization. Use when creating new zomes, implementing entry types, or modifying Holochain DNA code.
| name | nondominium-holochain-dna-dev |
| description | Specialized skill for nondominium Holochain DNA development, focusing on zome creation, entry patterns, integrity/coordinator architecture, ValueFlows compliance, and WASM optimization. Use when creating new zomes, implementing entry types, or modifying Holochain DNA code. |
This skill transforms Claude into a specialized nondominium Holochain DNA development assistant, providing expert guidance for creating zomes, implementing entry patterns, and following ValueFlows standards.
Use this skill when:
Do NOT use for:
Create new zomes following nondominium's 3-zome architecture pattern:
Initialize Zome Structure
./scripts/create_zome.sh <zome_name> both
Implement Integrity Layer
lib.rsassets/entry_types/ for templatesImplement Coordinator Layer
use zome_<name>_integrity::*;assets/function_templates/ for patternsConfigure Dependencies
# Cargo.toml
[zome_traits]
hdk_integrity = "zome_<name>_integrity"
Validate Structure
./scripts/sync_integrity_coordinator.sh <zome_name>
Follow ValueFlows-compliant entry patterns:
Define Entry Structure - NO TIMESTAMP FIELDS
#[hdk_entry_helper]
#[derive(Clone, PartialEq)]
pub struct EconomicResource {
// Business fields
pub resource_specification: ActionHash, // Link to spec
pub current_state: String,
// Agent information (NO timestamps!)
pub created_by: AgentPubKey,
}
Create Input Structure
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateEconomicResourceInput {
pub resource_specification: ActionHash,
pub current_state: String,
}
Implement Create Function
agent_info()?.agent_initial_pubkeycreated_at fieldAdd Discovery Patterns
// Global anchor - discoverable by everyone
let path = Path::from("resources");
create_link(path.path_entry_hash()?, entry_hash, LinkTypes::AllResources, LinkTag::new("resource"))?;
// Agent link - discoverable by agent
create_link(agent_pubkey, entry_hash, LinkTypes::AgentToResources, LinkTag::new("created"))?;
// Hierarchical link - facility to its specification
create_link(facility_hash, spec_hash, LinkTypes::SpecificationToFacility, LinkTag::new("implements"))?;
Get Timestamps from Action Headers When Needed
let record = get(entry_hash, GetOptions::default())?;
let action = record.action().as_create()?;
let created_at = action.timestamp();
Build WASM
./scripts/build_wasm.sh release [zome_name]
Validate Patterns
./scripts/validate_entry.sh <zome_name>
Check Performance
Package hApp
./scripts/package_happ.sh production
NEVER use SQL-style foreign keys in entry fields!
// ❌ WRONG - Direct ActionHash references
struct BadFacility {
pub facility_hash: ActionHash, // SQL-style foreign key
pub owner: ActionHash, // Should be a link instead
}
// ✅ CORRECT - Use links for relationships
struct GoodFacility {
pub conforms_to: ActionHash, // Link to specification
// No direct references to other entries
}
// ✅ CORRECT - Link patterns for relationships
create_link(facility_hash, owner_hash, LinkTypes::FacilityToOwner, LinkTag::new("managed_by"))?;
Use Holochain's built-in header metadata:
// ❌ WRONG - Manual timestamps
struct BadEntry {
pub created_at: Timestamp, // Redundant!
pub updated_at: Timestamp, // Redundant!
}
// ✅ CORRECT - No timestamps in entries
struct GoodEntry {
pub name: String,
pub description: String,
// No created_at/updated_at fields
}
// Get timestamps from action header when needed:
let record = get(entry_hash, GetOptions::default())?;
let action = record.action().as_create()?;
let created_at = action.timestamp();
Use #[hdk_entry_helper] macro with proper validation requirements:
#[hdk_entry_helper]
#[derive(Clone, PartialEq)]
pub struct FacilitySpecification {
pub name: String,
pub description: String,
pub facility_type: String, // Use Display impl for enums
pub created_by: AgentPubKey,
pub is_active: bool,
// NO ActionHash fields for relationships
}
#[hdk_entry_types]
#[unit_enum(UnitEntryTypes)]
pub enum EntryTypes {
#[entry_def(required_validations = 2)] // Specify validation requirements
FacilitySpecification(FacilitySpecification),
#[entry_def(required_validations = 2)]
EconomicFacility(EconomicFacility),
#[entry_def(required_validations = 3)] // Higher validation for bookings
FacilityBooking(FacilityBooking),
#[entry_def(required_validations = 2, visibility = "private")]
PrivateFacilityData(PrivateFacilityData),
}
🆕 NEW - Advanced Validation Options:
#[hdk_entry_types]
#[unit_enum(UnitEntryTypes)]
pub enum EntryTypes {
// Public entry with standard validation
#[entry_def(required_validations = 2)]
PublicEntry(PublicEntry),
// Private entry with higher validation
#[entry_def(required_validations = 5, visibility = "private")]
PrivateEntry(PrivateEntry),
// Entry with custom name
#[entry_def(name = "custom_entry", required_validations = 3)]
CustomEntry(CustomEntry),
}
🆕 NEW - Base64 Agent Keys Option: For web-compatible applications, consider base64 encoded agent keys:
#[hdk_entry_helper]
#[derive(Clone, PartialEq)]
pub struct FacilitySpecification {
pub name: String,
pub description: String,
pub created_by: AgentPubKeyB64, // Base64 encoded for web compatibility
pub is_active: bool,
}
Use comprehensive link types for discovery:
#[hdk_link_types]
pub enum LinkTypes {
// Discovery anchors
AllFacilitySpecifications,
AllEconomicFacilities,
// Hierarchical relationships
SpecificationToFacility, // FacilitySpec -> EconomicFacility
FacilityToBookings, // EconomicFacility -> FacilityBookings
// Agent-centric patterns
AgentToOwnedSpecs, // Agent -> FacilitySpecs they created
AgentToManagedFacilities, // Agent -> EconomicFacilities they manage
// Type-based discovery
SpecsByType, // FacilityType -> FacilitySpecs
FacilitiesByLocation, // Location -> EconomicFacilities
FacilitiesByState, // FacilityState -> EconomicFacilities
}
create_[entry_type] - Creates new entries with validation and linksget_[entry_type] - Retrieves single entry by hashget_all_[entry_type] - Global discovery via anchor linksget_my_[entry_type] - Agent-specific entries onlyupdate_[entry_type] - Updates existing entries with permission checksdelete_[entry_type] - Soft deletes with author validationDefine custom error types for each zome:
#[derive(Debug, thiserror::Error)]
pub enum ZomeError {
#[error("Entry not found: {0}")]
EntryNotFound(String),
#[error("Insufficient capability: {0}")]
InsufficientCapability(String),
#[error("Validation failed: {0}")]
ValidationError(String),
}
impl From<ZomeError> for WasmError {
fn from(err: ZomeError) -> Self {
error!(err.to_string())
}
}
Use structured link tagging for efficient queries:
// Discovery anchors
LinkTag::new("facility")
LinkTag::new("category")
// Status-based tags
LinkTag::new("available")
LinkTag::new("occupied")
// Relationship tags
LinkTag::new("created")
LinkTag::new("managed_by")
Implement standard ValueFlows entities:
Use standard ValueFlows actions:
produce, accept, modifytransfer, move, deliver_serviceconsume, use, worktransfer-custody, certify, reviewValidate ValueFlows compliance:
Call integrity functions across zomes:
let result: ExternResult<ValidationStatus> = call_integrity(
zome_info()?.zome_id,
"validate_resource_access".into(),
CapSecret::default(),
ValidateAccessInput {
agent: agent_pubkey,
resource: resource_hash,
},
)?;
Call functions on other agents' zomes:
let result: ExternResult<ResourceDetails> = call_remote(
agent_pubkey,
zome_zome_resource.zome_name,
"get_resource_details".into(),
CapSecret::default(),
resource_hash,
)?;
✅ CORRECT Cross-Zome Data Access
Use link queries to find related data, then retrieve entries:
// Find all resources managed by agent
let links = get_links(agent_pubkey, LinkTypes::AgentToResources, None)?;
let resource_hashes: Vec<ActionHash> = links.iter()
.map(|link| link.target.clone())
.collect();
// Retrieve each resource entry
let mut resources = Vec::new();
for hash in resource_hashes {
if let Some(record) = get(hash, GetOptions::default())? {
if let Some(entry) = record.entry().as_app_entry() {
if let EntryTypes::EconomicResource(resource) = entry {
resources.push(resource);
}
}
}
}
❌ WRONG - Direct Cross-Zome Entry Access
Never access entries from other zomes directly in your entry fields:
// WRONG - Never store direct references like this
struct BadResource {
pub owner: ActionHash, // SQL-style foreign key!
pub facility: ActionHash, // Direct reference!
}
// CORRECT - Use links instead
struct GoodResource {
pub name: String,
pub description: String,
// No direct ActionHash references
}
// Create relationships with links
create_link(resource_hash, owner_hash, LinkTypes::ResourceToOwner, LinkTag::new("owned_by"))?;
create_link(resource_hash, facility_hash, LinkTypes::ResourceToFacility, LinkTag::new("located_at"))?;
Based on recent Holochain projects, here's the modern validation pattern:
#[hdk_extern]
pub fn validate(op: Op) -> ExternResult<ValidateCallbackResult> {
match op {
Op::StoreRecord(_) => Ok(ValidateCallbackResult::Valid),
Op::StoreEntry { .. } => Ok(ValidateCallbackResult::Valid),
Op::RegisterCreateLink(create_link) => {
let (create, _action) = create_link.create_link.into_inner();
let link_type = LinkTypes::try_from(ScopedLinkType {
zome_index: create.zome_index,
zome_type: create.link_type,
})?;
// Link-specific validation logic
match link_type {
LinkTypes::AgentToResource => {
// Validate agent has permission to create this link
Ok(ValidateCallbackResult::Valid)
}
LinkTypes::ResourceToSpecification => {
// Validate resource exists and specification is valid
let _resource: Resource = must_get_entry(create.target_address.clone().into())?.try_into()?;
Ok(ValidateCallbackResult::Valid)
}
_ => Ok(ValidateCallbackResult::Invalid("Unknown link type".to_string())),
}
}
Op::RegisterDeleteLink(_) => {
Ok(ValidateCallbackResult::Invalid("Deleting links isn't valid".to_string()))
}
Op::RegisterUpdate { .. } => {
Ok(ValidateCallbackResult::Invalid("Updating entries isn't valid".to_string()))
}
Op::RegisterDelete { .. } => {
Ok(ValidateCallbackResult::Invalid("Deleting entries isn't valid".to_string()))
}
Op::RegisterAgentActivity { .. } => Ok(ValidateCallbackResult::Valid),
}
}
Modern projects use link tags for validation data:
Op::RegisterCreateLink(create_link) => {
let link_type = LinkTypes::try_from(ScopedLinkType {
zome_index: create.zome_index,
zome_type: create.link_type,
})?;
if link_type == LinkTypes::Attestation {
// Extract agent from link tag and validate against entry
let agent = AgentPubKey::try_from(
SerializedBytes::try_from(create.tag.clone())
.map_err(|e| wasm_error!(e))?
).map_err(|e| wasm_error!(e))?;
let attestation: Attestation = must_get_entry(create.target_address.clone().into())?.try_into()?;
if AgentPubKey::from(attestation.about) == agent {
Ok(ValidateCallbackResult::Valid)
} else {
Ok(ValidateCallbackResult::Invalid("Tag doesn't point to about".to_string()))
}
} else {
Ok(ValidateCallbackResult::Valid)
}
}
wee_alloc for memory allocationImplement hierarchical capability levels:
// Check capability before operations
if !agent_has_capability(&agent_pubkey, "create_resource") {
return Err(ZomeError::InsufficientCapability(
"Agent lacks 'create_resource' capability".to_string()
).into());
}
// Store capability grants as entries
let capability = CapabilityEntry {
agent: target_agent,
role: "contributor".to_string(),
capability_level: 300,
granted_by: agent_pubkey,
expires_at: Some(expiration_time),
// ... other fields
};
Critical Pattern Validation:
#[hdk_entry_helper] macro usage on all structsStandard Validation:
#[hdk_entry_helper] macro on all entry structscreated_at or updated_at to entriesExecutable automation scripts for DNA development:
create_zome.sh - Creates new zomes with integrity/coordinator structurebuild_wasm.sh - Compiles Rust code to WASM with optimizationvalidate_entry.sh - Validates entry creation patterns and conventionssync_integrity_coordinator.sh - Ensures layer consistency across zomespackage_happ.sh - Packages hApp bundles for distributionComprehensive documentation for DNA development patterns:
zome_patterns.md - Core architectural patterns and conventionsvalueflows_compliance.md - ValueFlows implementation guidelinesentry_creation_patterns.md - Detailed entry creation workflowsperformance_patterns.md - Optimization techniques and best practicesCode templates and boilerplate for rapid DNA development:
zome_template/ - Complete integrity/coordinator zome templatesentry_types/ - Common entry type patterns (basic, ValueFlows, capabilities)function_templates/ - CRUD and query function templatesNote: This skill is specifically tailored for the nondominium project's ValueFlows-based economic resource sharing architecture and should not be used for generic Holochain development outside this context.