1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// SPDX-License-Identifier: Apache-2.0
//! # axgf-rs — Reference implementation of the Axiom Genealogy Format (AXGF) 1.0
//!
//! This crate is the canonical Rust implementation of the [AXGF specification].
//! It provides a **stateless, data-oriented boundary**: every public function
//! takes JSON strings or bytes and returns a single uniform [`boundary::envelope::Envelope`]
//! serialized to JSON. No native Rust types cross the boundary — this is what
//! makes language bindings mechanical.
//!
//! ## Design contract (V1)
//!
//! 1. **Stateless & immutable.** Every operation takes a bundle in, returns a
//! new bundle out. No sessions, handles, or hidden mutation.
//! 2. **Flat JSON is the working form.** The on-disk `.axgf` is a ZIP, but the
//! library converts it to a single flat JSON object for all editing. ZIP is
//! read only by [`import_bundle`] and written only by [`export_bundle`].
//! 3. **No disk, no graph traversal, no query engine, no rendering in V1.**
//! The caller passes bytes; the library never touches the filesystem.
//! 4. **Explicit spec-version gating.** Every operation checks `manifest.axgf`
//! against [`SUPPORTED_SPEC_VERSIONS`] and refuses unknown versions.
//! 5. **Uniform envelope with stable diagnostic codes.** Validation is
//! non-blocking: operations may succeed with warnings.
//! 6. **Forward compatibility.** Unknown fields survive a round-trip untouched.
//!
//! [AXGF specification]: https://github.com/plkarin/axgf-spec
//!
//! ## Module layout
//!
//! - [`model`] — Typed structs for the 8 entity kinds and the manifest.
//! Internal to the library; never crosses the boundary.
//! - [`logic`] — Pure value-core: validation, CRUD, deduplication. Operates on
//! [`model`] types, never on raw JSON.
//! - [`boundary`] — The only layer that speaks JSON, ZIP and bytes: envelope
//! type, [`boundary::flat::FlatBundle`], and lifecycle helpers.
//! - [`convert`] — Foreign-format converters (GEDCOM 5.5.1 → AXGF).
//! - [`adapters`] — Thin per-target wrappers (rust, wasm, cffi, mobile) behind
//! feature flags.
//!
//! ## Minimal example
//!
//! Create an empty bundle, add a person, and validate the result. Every
//! function takes and returns JSON, wrapped in a uniform
//! [`boundary::envelope::Envelope`].
//!
//! ```
//! use axgf_rs::{add_entity, create_bundle, validate, EntityKind};
//! use axgf_rs::boundary::envelope::Status;
//!
//! // 1. Create an empty bundle. `data` is a serde_json::Value; convert to a
//! // string for the next call.
//! let bundle = create_bundle(Some("Karin")).data.to_string();
//!
//! // 2. Add a minimal person. The library generates a UUID v4 if none given
//! // and fills in `type` and `axgf_version`. The envelope's `data` here
//! // is `{ "id": <uuid>, "bundle": <updated flat bundle> }`.
//! let person = r#"{
//! "identity": {
//! "name": {"display": "Jean Pierre-Léonard", "components": []},
//! "gender": {"value": "M"},
//! "is_living": true
//! }
//! }"#;
//! let added = add_entity(&bundle, EntityKind::Person, person);
//! assert_eq!(added.status, Status::Ok);
//!
//! // 3. Structural + semantic validation over the updated bundle. Warnings
//! // are non-blocking, so `status == Ok` even if diagnostics are present.
//! let updated_bundle = added.data["bundle"].to_string();
//! let checked = validate(&updated_bundle);
//! assert_eq!(checked.status, Status::Ok);
//! ```
//!
//! ## Further reading
//!
//! - [`docs/API.md`] — a longer walk-through of every public function.
//! - [`SETUP.md`] — build instructions and per-target adapter notes.
//! - [AXGF specification] — the format itself.
//!
//! [`docs/API.md`]: https://github.com/plkarin/axgf-lib/blob/main/docs/API.md
//! [`SETUP.md`]: https://github.com/plkarin/axgf-lib/blob/main/SETUP.md
/// AXGF specification versions this build understands. Every lifecycle
/// operation verifies `manifest.axgf` against this set and refuses to proceed
/// on an unrecognized value with a stable `UNSUPPORTED_SPEC_VERSION`
/// diagnostic.
pub const SUPPORTED_SPEC_VERSIONS: & = &;
/// The AXGF specification version this build writes when creating or
/// re-exporting bundles.
pub const CURRENT_SPEC_VERSION: &str = "1.0";
// -------------------------------------------------------------------------
// Public API surface
//
// Every function on the boundary takes and returns JSON (as `&str` or bytes)
// and yields an `Envelope` serialized to a JSON string. See individual layer
// modules for the underlying implementations.
// -------------------------------------------------------------------------
use Envelope;
pub use ;
/// Create a new, empty AXGF bundle as flat JSON.
///
/// The optional `family_name` populates `manifest.family.name` when provided.
/// The returned envelope's `data` is the flat-bundle JSON.
/// Import a `.axgf` ZIP archive (bytes) and return its flat-bundle JSON.
///
/// The manifest's `axgf` version is checked against [`SUPPORTED_SPEC_VERSIONS`]
/// and the operation fails with `UNSUPPORTED_SPEC_VERSION` on mismatch.
/// Export a flat-bundle JSON string to a `.axgf` ZIP archive.
///
/// Stats are recomputed and the canonical JSON Schema is embedded. The
/// returned envelope's `data` carries the ZIP bytes as base64 in a
/// `{"zip_base64": ...}` object.
/// Return manifest and computed stats for the given flat bundle without
/// modifying it.
/// Validate a flat bundle structurally (JSON Schema) and semantically
/// (dangling refs, cycles, chronology, duplicate unique refs). Warnings do
/// **not** cause a non-`ok` status.
/// Add a new entity of the given kind to a flat bundle. A UUID v4 is
/// generated when `entity_json.id` is missing.
/// Update an existing entity in a flat bundle, keyed by `id`.
/// Delete an entity by id, applying the caller's referential-integrity
/// [`DeletePolicy`].
/// Run the safe deduplication passes on a flat bundle. Ambiguous merges are
/// flagged with `MANUAL_REVIEW_REQUIRED` diagnostics rather than performed.
/// Convert a GEDCOM 5.5.1 byte stream to a flat AXGF bundle.
///
/// - `default_confidence` is applied to imported facts when the source implies
/// no explicit confidence.
/// - `place_lang` is the BCP 47 language tag stored on imported `Place` names
/// when the GEDCOM record has no explicit language.