-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Background
We can sync domain contacts from OpenSRS into the local SQLite database, but there's no path to push changes back to the registry. This means macaw is currently read-only with respect to contact information — you can see what's registered but can't fix a typo, update a phone number, or change an address without going directly to the OpenSRS reseller console.
Current State
The existing implementation is half of a round-trip:
src/db/contacts.rshasfind_or_create_contact()for deduplication, but noupdate_contact()pathsrc/opensrs/xml.rsdeserialize_domain_all_info()initializes contact variables toNoneat lines 282–285 but never actually populates them from the XMLsrc/sync/mod.rsmaps contacts one-way: OpenSRS → local DB
What Needs to Be Built
1. Fix the incomplete contact XML deserializer (src/opensrs/xml.rs)
deserialize_domain_all_info() declares four contact variables that are always None. The parser needs state machine entries to handle contact_set → owner/admin/billing/tech → first_name/last_name/org_name/email/phone/fax/address1/address2/city/state/country/postal_code.
2. Add SET_CONTACT request/response types (src/opensrs/types.rs)
New structs for the OpenSRS CONTACT object SET action. The outbound contact fields use OpenSRS naming (org_name, state, country) which differs from the DB schema (organization, state_province, country_code) — mapping needs to be explicit and documented.
3. XML serialization for contact update requests (src/opensrs/xml.rs)
A serialize_set_contact_request() function following the same string-building pattern used for domain requests. The contact set block nests four contact types each with ~12 fields.
4. Add update_contact() to the DB layer (src/db/contacts.rs)
Currently find_or_create_contact() is the only entry point. We need a function that updates an existing contact record in place. Important: contacts are reusable across multiple domains via domain_contacts. Updating a shared contact changes data for every domain linked to it — callers need to decide whether to update in place or create a new contact record and re-link the domain.
5. New OpenSrsClient::update_domain_contacts() method (src/opensrs/client.rs)
Handles authentication, XML serialization, HTTP dispatch, and response parsing for the SET_CONTACT operation. Should accept a domain name and a ContactSet and return a result.
6. CLI subcommand
A new subcommand (e.g., macaw contacts update <domain>) that reads updated contact info (from a file, flags, or interactive prompt — TBD), calls the OpenSRS client, updates the local DB, and writes an audit log entry.
7. Audit logging
Per the security considerations in CLAUDE.md, all contact changes must write to audit_log with the old and new values as JSON snapshots.
Tricky Bits
Field name mapping between OpenSRS and the local schema:
| OpenSRS field | DB column |
|---|---|
org_name |
organization |
state |
state_province |
country |
country_code |
Contact deduplication and shared contacts: The find_or_create_contact() function does exact-match deduplication, so the same contact record may be linked to multiple domains. An update workflow needs to handle this — probably by creating a new contact record and updating the domain_contacts link for the specific domain being changed, rather than mutating a shared record.
Acceptance Criteria
-
deserialize_domain_all_info()correctly populates contact fields from OpenSRS XML -
SET_CONTACTXML request serialization produces valid OpenSRS XML - Successful round-trip test: read contacts from OpenSRS, modify a field, push back, re-read and verify
-
audit_loghas entries for every contact change with old/new JSON snapshots - Contact deduplication behavior on update is documented and tested
- Field name mapping between OpenSRS and DB schema is centralized (not scattered across call sites)
Related
src/db/contacts.rs— current read-only contact persistencesrc/opensrs/xml.rslines 282–285 — stub contact variables waiting to be wired upsrc/sync/mod.rs— one-way sync that will need a complement for outbound changes- OpenSRS XCP API docs,
CONTACTobject,SETaction