• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanopub-registry / 28155387420

25 Jun 2026 07:53AM UTC coverage: 31.926% (-0.2%) from 32.089%
28155387420

push

github

web-flow
chore: enhance and standardize logging across multiple components (#116)

* chore(EntryStatus): enhance logging for null and unsupported status value handling

* chore(logging): standardize logger variable names across multiple classes

* chore(CoverageFilter): enhance logging for coverage filter initialization and type checks

* chore(RegistryPeerConnector): enhance logging for peer connection and nanopub fetching

* chore(logging): enhance logging for request handling and error reporting in multiple pages

* chore(MainVerticle): enhance logging for HTTP server startup, request routing, and POST processing

* chore(Task): improve logging messages

* chore(Task): enhance logging for server status checks and account loading processes

* chore(RegistryInfo): add logging messages for RegistryInfo snapshot assembly and JSON serialization

* chore(logging): enhance logging throughout various components for better traceability and debugging

* chore(Utils): enhance logging for user IRI extraction in IntroNanopub

* chore(TrustStatePage): enhance logging for trust-state snapshot resolution and querying

* chore(NanopubLoader): enhance logging for nanopub retrieval and processing

* chore(Task): enhance logging for task execution and status transitions

313 of 1106 branches covered (28.3%)

Branch coverage included in aggregate %.

1048 of 3157 relevant lines covered (33.2%)

5.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.73
src/main/java/com/knowledgepixels/registry/AgentFilter.java
1
package com.knowledgepixels.registry;
2

3
import com.mongodb.client.ClientSession;
4
import org.bson.Document;
5
import org.slf4j.Logger;
6
import org.slf4j.LoggerFactory;
7

8
import java.util.Collections;
9
import java.util.HashMap;
10
import java.util.Map;
11

12
import static com.knowledgepixels.registry.RegistryDB.collection;
13

14
/**
15
 * Controls which pubkeys are allowed to publish nanopubs and what their quotas are.
16
 * Configured via REGISTRY_COVERAGE_AGENTS env var.
17
 * <p>
18
 * Format: whitespace-separated entries, each being either:
19
 * - "viaSetting" — include all agents approved by the trust network (with computed quotas)
20
 * - "pubkeyHash:quota" — include a specific pubkey with an explicit quota
21
 * <p>
22
 * Example: viaSetting abc123...def456:5000 789xyz...abc012:10000
23
 * <p>
24
 * When unset, defaults to viaSetting (all trusted agents, no restrictions).
25
 */
26
public final class AgentFilter {
27

28
    private static final Logger logger = LoggerFactory.getLogger(AgentFilter.class);
9✔
29

30
    private static volatile boolean viaSetting = true;
6✔
31
    private static volatile boolean enforceQuota = false;
6✔
32
    private static volatile Map<String, Integer> explicitPubkeys = Collections.emptyMap();
9✔
33

34
    private AgentFilter() {
35
    }
36

37
    /**
38
     * Initializes the agent filter from the REGISTRY_COVERAGE_AGENTS env var.
39
     */
40
    public static void init() {
41
        String config = Utils.getEnv("REGISTRY_COVERAGE_AGENTS", "viaSetting");
12✔
42
        logger.debug("Initializing AgentFilter from REGISTRY_COVERAGE_AGENTS='{}'", config);
12✔
43

44
        boolean via = false;
6✔
45
        Map<String, Integer> pubkeys = new HashMap<>();
12✔
46

47
        for (String entry : config.trim().split("\\s+")) {
57✔
48
            if (entry.isEmpty()) {
9!
49
                continue;
×
50
            }
51
            if ("viaSetting".equals(entry)) {
12✔
52
                via = true;
9✔
53
            } else if (entry.contains(":")) {
12✔
54
                String[] parts = entry.split(":", 2);
15✔
55
                String pubkeyHash = parts[0];
12✔
56
                int quota;
57
                try {
58
                    quota = Integer.parseInt(parts[1]);
15✔
59
                } catch (NumberFormatException e) {
3✔
60
                    logger.error("Failed to parse quota in REGISTRY_COVERAGE_AGENTS entry '{}': '{}' is not a valid integer", entry, parts[1]);
21✔
61
                    throw new IllegalArgumentException("Invalid quota in REGISTRY_COVERAGE_AGENTS: " + entry);
18✔
62
                }
3✔
63
                pubkeys.put(pubkeyHash, quota);
18✔
64
            } else {
3✔
65
                logger.error("Unrecognized entry in REGISTRY_COVERAGE_AGENTS: '{}'", entry);
12✔
66
                throw new IllegalArgumentException("Invalid entry in REGISTRY_COVERAGE_AGENTS: " + entry + " (expected 'viaSetting' or 'pubkeyHash:quota')");
18✔
67
            }
68
        }
69

70
        viaSetting = via;
6✔
71
        enforceQuota = "true".equals(System.getenv("REGISTRY_ENFORCE_QUOTA"));
15✔
72
        explicitPubkeys = Collections.unmodifiableMap(pubkeys);
9✔
73

74
        if (via && pubkeys.isEmpty()) {
15✔
75
            logger.info("Agent filter: viaSetting (all trusted agents)");
12✔
76
        } else if (via) {
6✔
77
            logger.info("Agent filter: viaSetting + {} explicit pubkeys", pubkeys.size());
21✔
78
        } else {
79
            logger.info("Agent filter: {} explicit pubkeys only", pubkeys.size());
18✔
80
        }
81
        logger.info("Quota enforcement (REGISTRY_ENFORCE_QUOTA): {}", enforceQuota);
15✔
82

83
        if (via && "false".equals(System.getenv("REGISTRY_ENABLE_TRUST_CALCULATION"))) {
21!
84
            logger.warn("viaSetting is enabled but trust calculation is disabled — " +
×
85
                        "no agents will be discovered via the trust network; only explicit pubkeys will work");
86
        }
87
    }
3✔
88

89
    /**
90
     * Returns true if the trust network (viaSetting) is used for agent approval.
91
     */
92
    public static boolean usesViaSetting() {
93
        return viaSetting;
6✔
94
    }
95

96
    /**
97
     * Returns the explicitly configured pubkeys with their quotas.
98
     */
99
    public static Map<String, Integer> getExplicitPubkeys() {
100
        return explicitPubkeys;
6✔
101
    }
102

103
    /**
104
     * Returns the quota for a given pubkey, checking explicit config first,
105
     * then the accounts collection for trust-computed quotas.
106
     * Returns -1 if the pubkey is not allowed.
107
     */
108
    public static int getQuota(ClientSession session, String pubkeyHash) {
109
        // Explicit pubkeys take precedence
110
        if (explicitPubkeys.containsKey(pubkeyHash)) {
×
111
            int quota = explicitPubkeys.get(pubkeyHash);
×
112
            logger.trace("Pubkey {}: quota={} (explicit config)", pubkeyHash, quota);
×
113
            return quota;
×
114
        }
115

116
        // Check trust network if enabled
117
        if (viaSetting) {
×
118
            Document account = collection(Collection.ACCOUNTS.toString()).find(session,
×
119
                    new Document("pubkey", pubkeyHash).append("status", "loaded")).first();
×
120
            if (account != null && account.get("quota") != null) {
×
121
                int quota = account.getInteger("quota");
×
122
                logger.trace("Pubkey {}: quota={} (account status=loaded)", pubkeyHash, quota);
×
123
                return quota;
×
124
            }
125
            // Also accept toLoad accounts (approved but not yet fully loaded)
126
            account = collection(Collection.ACCOUNTS.toString()).find(session,
×
127
                    new Document("pubkey", pubkeyHash).append("status", "toLoad")).first();
×
128
            if (account != null && account.get("quota") != null) {
×
129
                int quota = account.getInteger("quota");
×
130
                logger.trace("Pubkey {}: quota={} (account status=toLoad)", pubkeyHash, quota);
×
131
                return quota;
×
132
            }
133
        }
134

135
        logger.trace("Pubkey {}: no quota found (not allowed)", pubkeyHash);
×
136
        return -1; // not allowed
×
137
    }
138

139
    /**
140
     * Returns true if the given pubkey is allowed to publish (has a quota >= 0).
141
     * Always returns true if quota enforcement is disabled.
142
     */
143
    public static boolean isAllowed(ClientSession session, String pubkeyHash) {
144
        if (!enforceQuota) {
×
145
            return true;
×
146
        }
147
        boolean allowed = getQuota(session, pubkeyHash) >= 0;
×
148
        if (!allowed) {
×
149
            logger.debug("Pubkey {}: not allowed (no quota entry found)", pubkeyHash);
×
150
        }
151
        return allowed;
×
152
    }
153

154
    /**
155
     * Returns true if the given pubkey has exceeded its quota.
156
     * Always returns false if quota enforcement is disabled.
157
     */
158
    public static boolean isOverQuota(ClientSession session, String pubkeyHash) {
159
        if (!enforceQuota) {
×
160
            return false;
×
161
        }
162
        int quota = getQuota(session, pubkeyHash);
×
163
        if (quota < 0) {
×
164
            logger.debug("Pubkey {}: treated as over quota (not allowed at all)", pubkeyHash);
×
165
            return true; // not allowed at all
×
166
        }
167

168
        // Count nanopubs for this pubkey via the "$" list position
169
        Document listDoc = collection("lists").find(session,
×
170
                new Document("pubkey", pubkeyHash).append("type", "$")).first();
×
171
        long currentCount = (listDoc != null && listDoc.get("maxPosition") != null)
×
172
                ? listDoc.getLong("maxPosition") + 1 : 0;
×
173

174
        boolean over = currentCount >= quota;
×
175
        if (over) {
×
176
            logger.debug("Pubkey {}: over quota ({} / {})", pubkeyHash, currentCount, quota);
×
177
        } else {
178
            logger.trace("Pubkey {}: under quota ({} / {})", pubkeyHash, currentCount, quota);
×
179
        }
180
        return over;
×
181
    }
182

183
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc