📄 PublicLibraryStorage.sol
D-OPEN SOVEREIGN
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 *
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 *
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15
16// SPDX-License-Identifier: Apache-2.0
17pragma solidity ^0.8.24;
18
19import {ErrorLibrary} from "./ErrorLibrary.sol";
20
21contract PublicLibraryStorage {
22
23    enum LibraryOwnership {
24        Public,
25        Private
26    }
27
28    // International cataloging / interchange standards a library can expose its catalog in.
29    enum PreferredFormat {
30        MARC21,
31        UNIMARC,
32        MARCXML,
33        DublinCore,
34        MODS,
35        BIBFRAME,
36        ONIX,
37        OPDS,
38        InternetArchive,
39        HathiTrust,
40        EAD,
41        Other
42    }
43
44    struct PublicLibrary {
45        uint256 id;
46        string name;
47        string physicalAddress;
48        string country;
49        string language;
50        LibraryOwnership ownership;
51        string website;
52        PreferredFormat preferredFormat;
53        uint64 createdAt;
54        uint64 updatedAt;
55    }
56
57    struct PublicLibraryInput {
58        string name;
59        string physicalAddress;
60        string country;
61        string language;
62        LibraryOwnership ownership;
63        string website;
64        PreferredFormat preferredFormat;
65    }
66
67    // State Variables
68    address public admin; // single admin or multi-sig if you choose
69    mapping(address => bool) public _isAuthorized; // reserved for future write access (unused for now)
70
71    mapping(uint256 => PublicLibrary) private libraries;
72    uint256 private _nbLibraries;
73
74    event AuthorizedAdded(address indexed caller);
75    event AuthorizedRemoved(address indexed caller);
76    event PublicLibraryAdded(uint256 indexed id, string name);
77    event PublicLibraryUpdated(uint256 indexed id);
78
79    // Modifiers
80    modifier onlyAdmin() {
81        require(msg.sender == admin, "not admin");
82        _;
83    }
84
85    modifier onlyAuthorized() {
86        require(_isAuthorized[msg.sender], "not authorized");
87        _;
88    }
89
90    constructor() {
91        admin = msg.sender;
92    }
93
94    // ===== Admin / authorization (reserved for future write access) =====
95    function isAuthorized(address caller) public view returns (bool) {
96        require(caller != address(0), "zero addr");
97        return _isAuthorized[caller];
98    }
99
100    function addAuthorized(address caller) public onlyAdmin {
101        require(caller != address(0), "zero addr");
102        _isAuthorized[caller] = true;
103        emit AuthorizedAdded(caller);
104    }
105
106    function removeAuthorized(address caller) public onlyAdmin {
107        _isAuthorized[caller] = false;
108        emit AuthorizedRemoved(caller);
109    }
110
111    // ===== Public library lifecycle (admin-only for now) =====
112    function addPublicLibrary(PublicLibraryInput calldata input) external onlyAdmin returns (uint256 id) {
113        _nbLibraries++;
114        id = _nbLibraries;
115
116        uint64 nowTs = uint64(block.timestamp);
117
118        libraries[id] = PublicLibrary({
119            id: id,
120            name: input.name,
121            physicalAddress: input.physicalAddress,
122            country: input.country,
123            language: input.language,
124            ownership: input.ownership,
125            website: input.website,
126            preferredFormat: input.preferredFormat,
127            createdAt: nowTs,
128            updatedAt: nowTs
129        });
130
131        emit PublicLibraryAdded(id, input.name);
132    }
133
134    function updatePublicLibrary(uint256 id, PublicLibraryInput calldata input) external onlyAdmin {
135        if (!libraryExists(id)) revert ErrorLibrary.InvalidPublicLibraryId();
136
137        PublicLibrary storage lib = libraries[id];
138        lib.name = input.name;
139        lib.physicalAddress = input.physicalAddress;
140        lib.country = input.country;
141        lib.language = input.language;
142        lib.ownership = input.ownership;
143        lib.website = input.website;
144        lib.preferredFormat = input.preferredFormat;
145        lib.updatedAt = uint64(block.timestamp);
146
147        emit PublicLibraryUpdated(id);
148    }
149
150    // ===== Reads =====
151    function libraryExists(uint256 id) public view returns (bool) {
152        return id > 0 && id <= _nbLibraries;
153    }
154
155    function getPublicLibrary(uint256 id) external view returns (PublicLibrary memory) {
156        if (!libraryExists(id)) revert ErrorLibrary.InvalidPublicLibraryId();
157        return libraries[id];
158    }
159
160    function nbLibraries() external view returns (uint256) {
161        return _nbLibraries;
162    }
163}
164