|
|
|
@@ -328,9 +328,10 @@ class SessionManagerTest {
|
|
|
|
|
void rosterViewExposesTheCharterReceiptButNeverTheCharterText() {
|
|
|
|
|
// The roster (fleet_list and GET /members both render through rosterView) must let a lead
|
|
|
|
|
// see which charter a member got, without ever carrying the charter prose itself (CB-571).
|
|
|
|
|
String composed = "role charter\n\nreply";
|
|
|
|
|
CharterReceipt receipt = CharterReceipt.compose(MemberRole.DEV, "prof", "role charter", composed);
|
|
|
|
|
MemberSession s = new MemberSession("p1", "term1", "prof", MemberRole.DEV, "/cwd", null,
|
|
|
|
|
0, 0, 0, MemberSession.State.READY, null, null,
|
|
|
|
|
CharterReceipt.compose(MemberRole.DEV, "prof", "role charter", "role charter\n\nreply"), null);
|
|
|
|
|
0, 0, 0, MemberSession.State.READY, null, null, receipt, null);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> view = SessionManager.rosterView(s, null);
|
|
|
|
|
|
|
|
|
@@ -338,10 +339,49 @@ class SessionManagerTest {
|
|
|
|
|
"the config key that supplied the role charter is reported");
|
|
|
|
|
assertEquals(CharterReceipt.digestOf("role charter\n\nreply"), view.get("charterSha256"),
|
|
|
|
|
"the digest of the exact composed charter bytes is reported");
|
|
|
|
|
// #604: the byte count rides alongside the digest, and must match what the receipt itself
|
|
|
|
|
// carries (not a hardcoded literal) so a bug that reads the wrong field is caught.
|
|
|
|
|
assertEquals(receipt.charterBytes(), view.get("charterBytes"),
|
|
|
|
|
"the exact composed byte count is reported, read from the receipt");
|
|
|
|
|
assertEquals(composed.getBytes(java.nio.charset.StandardCharsets.UTF_8).length, view.get("charterBytes"),
|
|
|
|
|
"the byte count is the real UTF-8 length of the composed charter");
|
|
|
|
|
assertFalse(view.values().toString().contains("role charter"),
|
|
|
|
|
"the roster row must not embed the charter text itself");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void rosterViewOmitsCharterBytesAndDigestWhenNoCharterWasComposed() {
|
|
|
|
|
// #604: a member with no role charter and no reply charter (composed == null) still reports
|
|
|
|
|
// charterSource ("none"), but neither a digest nor a size — the digest is absent, and the
|
|
|
|
|
// size only ever accompanies a real digest. This must not be satisfiable by code that always
|
|
|
|
|
// writes charterBytes.
|
|
|
|
|
CharterReceipt receipt = CharterReceipt.compose(MemberRole.DEV, "prof", null, null);
|
|
|
|
|
MemberSession s = new MemberSession("p1", "term1", "prof", MemberRole.DEV, "/cwd", null,
|
|
|
|
|
0, 0, 0, MemberSession.State.READY, null, null, receipt, null);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> view = SessionManager.rosterView(s, null);
|
|
|
|
|
|
|
|
|
|
assertEquals(CharterReceipt.NO_SOURCE, view.get("charterSource"),
|
|
|
|
|
"no configured role or reply charter reports the explicit \"none\" source");
|
|
|
|
|
assertFalse(view.containsKey("charterSha256"), "no digest is reported when no charter was composed");
|
|
|
|
|
assertFalse(view.containsKey("charterBytes"), "no byte count is reported when no charter was composed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void rosterViewOmitsCharterFieldsEntirelyWhenTheReceiptItselfIsAbsent() {
|
|
|
|
|
// #604 acceptance criterion 3: charterReceipt() can be null on its own (a session recorded
|
|
|
|
|
// before CB-571, or a launcher that never composed one) — the outer null-guard must still
|
|
|
|
|
// suppress charterSource, charterSha256 AND charterBytes together.
|
|
|
|
|
MemberSession s = new MemberSession("p1", "term1", "prof", MemberRole.DEV, "/cwd", null,
|
|
|
|
|
0, 0, 0, MemberSession.State.READY, null, null, null, null);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> view = SessionManager.rosterView(s, null);
|
|
|
|
|
|
|
|
|
|
assertFalse(view.containsKey("charterSource"), "no charter fields at all when the receipt is null");
|
|
|
|
|
assertFalse(view.containsKey("charterSha256"), "no charter fields at all when the receipt is null");
|
|
|
|
|
assertFalse(view.containsKey("charterBytes"), "no charter fields at all when the receipt is null");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void aNullTerminalFromThePrimaryIsANoOpEvenWithSessionsRegistered() {
|
|
|
|
|
// The primary resolves to a Principal with no terminal, and FleetMcp's context extractor
|
|
|
|
|