Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · kamo-internal

    A member's teams on the profile's Position card, saved to the member-side route, and the waterfall hint names teams (KamoCollab CP01 T24)

    The Position card gains Teams under the job title: chips for every viewer of the card, a multiple pick over the organization's teams for a security administrator, saved as {teamIds} to PUT **************** (endpoint memberTeams). Teams the profile could not read are not offered for editing, so a save never replaces teams nobody saw (CP01-T14-4). A refusal shows on the field in the dictionary's words where it has them. The member security tab's hint names teams, and Team: sources get a tone of their own.

  2. · kamo-shared-library

    The 60-key trait registry, the group defaults and the Docstion vocabulary (KamoCollab CP03 T4)

    PersonalityTraitKey carries a TraitSpec per key (family, type, range, default, choices, linked keys, UI group, unit, adaptability, label keys), REGISTRY_VERSION cp03-1, fromName and choiceLabelKey; PersonalityDefaults holds the CHANNEL_ORDER, ETIQUETTE and DECISION_PRIORITY defaults of spec 5.3.4. The collab package adds CollabKind and the three restrictive level enums plus the escalation triggers. Pure classes, no beans; nothing reads them yet.

  3. · SecurityService

    The hand-applied DDL for the charter ORG layer, the personality and Docstion columns and org archetypes, and its contract test (KamoCollab CP03 T2)

    Spec §5.1's block, character for character: the twelve nullable trait/collab columns on the five charter owner tables, org_charter_items (cascading with its org), org_personality_archetypes (unique title per org, case-insensitive) and their items (cascading with the archetype), and one partial archetype_ref index per owner table for the archetype in-use check. Task 3 applies it.

  4. · kamo-internal

    The Teams tab on Essential Setup, in the settings menu, on the Settings landing page and on the home admin bar (KamoCollab CP01 T23)

    /settings/essential?tab=teams mounts TeamManager after Job titles, with its help column (purpose, features with the rights waterfall, best practices, the charter article). The settings menu gains { key: 'teams' } after jobTitles, the landing page a Teams card beside Departments and Job titles, and the home admin bar a Teams entry after Job Titles (master R1-37). Tests: essentialSetupExposure pins R1-37 (every Essential Setup menu entry has a landing card and an admin-bar entry, in menu order); settingsLandingCards resolves every landing card's runtime-built keys, which check-i18n-keys cannot see; teamsTab pins the tab's place, component and help.

  5. · kamo-internal

    TeamManager's team dialog — name, timeout, members and lead, description and charter, roles and rights, saved in one call (KamoCollab CP01 T22)

    Add Team, each row's Edit and the empty state's call to action open one dialog: the name, the session timeout, the members (chips, and the member picker opened on the current members), the lead (chosen from those members, "No lead" allowed), the description with its counter, CharterEditor at the TEAM level, the associated roles with none forced in (D15), and the direct rights through PermissionGroups. One POST or PUT sends every field; NOT_SPECIFIED is never sent. A refusal is said in its own words, at its field when it has one; rightsRecalculated: false offers Recalculate permissions. The live refresh pauses while the dialog is open. The multi-select picker gains initialPicked: it opens on people already chosen, and its answer is the whole selection.

  6. · SecurityService

    The visible listing's inputs come from the org graph — subordinates, AI supervisees and AI members as id strings; the manager and AI supervisor pairs are gone (KamoCollab CP02 T15)

    **************** now takes the caller and reads the organization's org graph from the 60 s cache (orgGraphCache.get): - subordinateMemberIds = reports(caller, true) that are record-active and not synthetic, only with the subordinate right and not the all-org right; - aiSuperviseeIds = the AI nodes whose supervisor is the caller (never itself); - aiMemberIds = every AI node; - orgMemberIds (all-org right only) and names as before. It no longer calls access.managerPairs or aiMembers.artificialMembers for visibility. VisibilityInputs.toBody() sends the three sets as strings in place of managerPairs and aiSupervisorPairs. **************** and its TeamMemberRepo dependency are deleted. A record-inactive middle manager no longer hides the reports below them (D19); a TERMINATED member whose record is still active stays a subordinate, as the pair walk's tm.recordState.isActive filter kept them. ComputeService accepts the sets since CP02 T14 (deployed); T16 removes its pair walk only after this is live.

  7. · SecurityService

    GET /api/security/org-chart — the people org chart from the org graph: team members who are not synthetic, inactive ones flagged, departments with their heads, teams with their leads, every id a string and no level, role or right (KamoCollab CP02 T13)

  8. · kamo-internal

    TeamManager, the teams table — rows, load states and delete (KamoCollab CP01 T21)

    The Teams tab's table (spec §5.10, D22), as JobTitleManager lists job titles: team (title and the description's first line), members, lead, requirements, associated roles, direct rights and timeout, with the CommerceSkeleton, EmptyState and ErrorState-with-Retry states. Delete goes through ConfirmationDialog naming the member count; a refusal is said in teams.errors words, else the service's sentence. Live through useOrgChanges(['teams', 'member-security']), paused while the confirmation is open; every load is numbered, so a refresh in flight when a delete lands cannot bring the row back. Nothing mounts it until Task 23 adds the tab; Task 22 adds the Add and Edit buttons with their dialog.

  9. · SecurityService

    The manager line reads the org graph — cycle checks on a fresh graph, the directory on the cached one, and a member's own manager needs MANAGE_MEMBER_SECURITY to change (KamoCollab CP02 T12)

    - MemberSecurityController: rejectManager keeps the self, org and record-active refusals and tests the loop with **************** the ten-level bound goes. touchesMemberSecurity gains managerId, compared like the department (only a real change needs the right; an unreadable id counts as one) (D21, D22). - ManagerStepHandler: the hire MANAGER step's loop check is the same test on a graph loaded inside its transaction; MANAGER_OF and the depth bound go. - TeamMemberDirectoryController: one cached graph per page, read only when a row asks; directReports = record-active reports(id, false), so supervised AIs count; the picker hint = candidate == member or managerChain(candidate) contains member.

  10. · kamo-internal

    The teams client — types, TeamsApiError and the ten calls over the team relays (KamoCollab CP01 T20)

    app/lib/teams/teamsApi.ts: Team, TeamDetail, TeamMemberRow, TeamRef, TeamWrite, TeamSaved; parseTeam (tolerant: ids as strings, missing lists [], a right whose setting is not GRANTED or NUKE dropped); TeamsApiError(message, status, reason, field, memberId), read from the body or the proxy's details wrapper, with only a sentence written for people as its message; and listTeams, getTeam, createTeam, updateTeam, deleteTeam, getTeamMembers, setTeamMembers, recalculateTeamRights, getMemberTeams, setMemberTeams over authenticatedFetch with credentials: 'include'.

  11. · kamo-internal

    The charter client knows TEAM, and the BFF relays teams (KamoCollab CP01 T19)

    CharterLevel gains TEAM and CharterSubject a hypothetical member's teamIds; saveLayer('TEAM') PUTs **************** Two relays: /api/security/teams/** (GET, POST, PUT, DELETE) and **************** (GET, PUT), each through forwardToApi and relayUpstream, segments re-encoded and dot segments refused. vitest now collects app/api/**/__tests__, where the relay test sits.

  12. · SecurityService

    Reports read the org graph — a TEAM scope and a TEAM share reach the whole subtree, supervised AIs included (KamoCollab CP02 T11)

    ReportScopeResolver.reportsTo is reports(member, true) of the cached graph: transitive and unbounded (the old walk stopped after ten levels), following the reporting line, so an AI with no manager is in its supervisor's team. A TEAM share reaches the manager its key names and everyone below them at any depth (it reached their direct reports only). No report names a team right and no TEAM share exists, so production output is unchanged.

  13. · SecurityService

    Teams at member creation — teamIds on create-team-member, checked before anything is written, joined inside the creation transaction before the first applied rights, announced after the commit (KamoCollab CP01 T14A)

    POST **************** (and the /create and /bulk-create paths that share MemberCreationService.create) take an optional teamIds for a person or an AI (master R1-36). Absent, null and [] name no team and need no right, so a create without teams is unchanged. - Checked after the AI checks and before the user lookup, each refusal with field teamIds and nothing written: 400 INVALID_FIELD, 403 NOT_ALLOWED without MANAGE_MEMBER_SECURITY or an open god window (Creator.maySetTeams, filled by creatorOf), 400 NOT_A_TEAM_MEMBER for a base member, 409 TOO_MANY_TEAMS over 25 (no read), 400 TEAM_NOT_FOUND for another org's or an unknown team, 400 TOO_MANY_MEMBERS for a full team (TeamValidator.newMemberTeams). - Written by TeamWriter.joinNewMember, MANDATORY with no @RetryOnDbConflict, through the new teams.NewMemberTeams, right after the member's save and before the mirror, the first applied rights (which so include the TEAM level) and an AI's hire; flushed, never caught: a member never exists with half its teams. A 40001 is retried whole by the caller (the existing 503 RETRY). - TeamService.afterCommit tells the TeamChangeListeners once the creation commits, never after a rollback; the welcome stays after the commit (a8966fd). Rulings CP01-T14A-1..3; master CP-D96.

  14. · kamo-internal

    The access log filter offers impersonation and Enter-As (KamoCollab CP00 T11)

    SecurityService now writes IMPERSONATION_STARTED, IMPERSONATION_ENDED and ENTER_AS into the org's access log. The event-type list (accessLogEvents.ts, which the filter and the grid both read) mirrors the shared library's enum and gains the three, in its order, said in the dictionary's words. A new test opens the filter itself and holds the three to AccessLogEventType; the Java enum parser moves into sharedLibPath so both tests share it.

  15. · SecurityService

    SecurityService's chat policy reads member facts from the org graph, a graph loaded per snapshot (KamoCollab CP02 T10)

    ChatPolicyBeanConfig builds ChatPolicySnapshotLoader with the graph constructor and orgGraphCache::fresh (ruling CP02-T17-3), as MediaService does, so the roster's chat annotations and the member card read the same facts as every other hierarchy question. The legacy chat facts repository is no longer injected; shared-lib removes it in Task 18. ChatPolicyBeanConfigTest: the loader's facts are MemberFactsFromGraph of the graph fresh() returns for the org id (never get()); no active set asks for no graph; the service keeps its snapshot until invalidated; a 59 s old cached graph is not used; and the beans wire in a context with no legacy repository, where the publisher and the NATS listener each make the next snapshot read a new graph. ReferenceOrgGraph becomes public with members() and build().

  16. · SecurityService

    A department gets a head — PUT **************** its writer, and the head's name and standing on the department reads (KamoCollab CP02 T9)

  17. · SecurityService

    Every SecurityService graph write announces the change, the team seam listens, and a ratchet keeps it so (KamoCollab CP02 T8)

    Each write path of CP02 spec §3.5 (W1-W15) calls **************** cause) with §5.4.2's causes: member security (roles, department, job title, manager, level, owner, member type), the profile PUT (status, intelligence, AI supervisor, compared with the values read before the save), member creation, registration, org create and leave, AI retire, the hire MANAGER step, departments, job titles, role delete, and portal and billing member creation. The security-provider mirror announces its own organization (ruling CP02-T8-1). OrgGraphTeamChangeListener implements CP01's TeamChangeListener seam with cause TEAM. OrgGraphPublisherCoverageTest (D15) fails when a file writes a graph fact without the publisher, outside COVERED_BY_SEAM (teams/TeamWriter.java) and ALLOWED (with reasons), naming the file, the line and the pattern.

  18. · SecurityService

    Teams on the member card and in the directory search — [{id, title}] by title, one team read per page (KamoCollab CP01 T16)

    GET /api/security/members/{id}/card names a team member's teams ([] in no team; left out when the read fails, as on the profile). GET **************** gives each team-member row its teams from one findTeamRefsByMemberIdIn for the page's team members (TeamService.teamsOfMembers, which teamsOf now uses, so there is one order rule); a plain member's row has no teams and is not asked about. /ai-members and /impersonation-targets are unchanged.

  19. · SecurityService

    Teams in the effective-rights views — the diagnostics cascade's teams level, and Team: sources on the applied rights (KamoCollab CP01 T15)

    The diagnostics cascade (GET **************** lists a team member's teams between the job title and the member, {teamId, title, roles, rights}, in the waterfall's order; the security view's applied rights name "Team: <title> (via role <role>)" and "Team: <title>" after the job title and before the member's own. One reader, teams.TeamLevelSources: the teams from TeamLevels, then their roles and direct rights; one query for a member in no team, none for a customer.

  20. · SecurityService

    A member's teams from the profile — GET|PUT **************** and teams on the profile and the security view (KamoCollab CP01 T14)

  21. · SecurityService

    PUT **************** — a team's charter-only save through TeamWriter, announced after the commit (KamoCollab CP01 T13)

    The team charter endpoint of spec §5.6/§5.7 on LayerCharterController, beside the role, department and job-title ones: CONFIGURE_SYSTEM or god; the path id, unknown team and another org's team are all 404 TEAM_NOT_FOUND (ruling CP01-T13-1); charterItems is required and [] clears; TeamWriter.updateCharter validates the items as the TEAM layer in its transaction, then TeamService.afterWrite announces the save once. A charter edit recalculates no one and is no graph fact. Answers {charterItems}. The team path-id rule (canonical UUID text, else 404 with no lookup, CP01-T10-1) moves from TeamController to TeamWire.pathTeamId so both controllers share it.

  22. · SecurityService

    The TEAM charter layer — a member's teams after the job title, the TEAM subject, teamIds, and team hide markers (KamoCollab CP01 T12)

    A member's teams become TEAM layers between the job title and the member, all at one rank and ordered by lower-case title then id; the teams' roles join the ROLE layer. Only staff are looked up, with one indexed query, so a member in no team resolves exactly as before (pinned against layers and effective items captured on the unchanged loader; no stamp hash, R1-1). A TEAM subject resolves its roles (rank 0), then the team's layer, with the dialog's unsaved roles, description, title and items. CharterSubject gains teamIds (a hypothetical member's teams); a team of another org, as a TEAM subject or in teamIds, is 404 SUBJECT_NOT_FOUND and none of its items or roles are read (Review Focus 4). CharterReferenceValidator finds team charter items: a TEAM marker may hide role, department and job-title items, a MEMBER marker may hide a team's item, and a team item of another org is SUPPRESS_TARGET_NOT_FOUND. **************** used TEAM as its unknown level; TEAM became a level in cp01:5, so it now uses PLANET.

  23. · kamo-internal

    "Calls from AI team members" on one's own profile (SP95 T27)

    A person's profile gains a card in its Work room: whether their organization's AI team members may phone them, and on which of their numbers. The switch turns a standing consent on for the number chosen (the first one by default) or off, and choosing another number while it is on moves the consent there; both save at once through the new BFF relay of SecurityService's ai-call-consent route. A consent left on a number that is no longer on the profile reads as off, with "Your number changed"; a profile with no number asks for one first. The card says a call asked for in a chat is allowed even when this is off, and re-reads when the member's record changes elsewhere. A security administrator sees a colleague's card read-only, captioned for someone else and naming who can change it. The gates are aiCallsView (self or MANAGE_MEMBER_SECURITY, on a saved person who is a team member) and aiCallsEdit (the person themself), with a palette row.

  24. · kamo-internal

    "Calls from AI team members" on one's own profile (SP95 T27)

    A person's profile gains a card in its Work room: whether their organization's AI team members may phone them, and on which of their numbers. The switch turns a standing consent on for the number chosen (the first one by default) or off, and choosing another number while it is on moves the consent there; both save at once through the new BFF relay of SecurityService's ai-call-consent route. A consent left on a number that is no longer on the profile reads as off, with "Your number changed"; a profile with no number asks for one first. The card says a call asked for in a chat is allowed even when this is off, and re-reads when the member's record changes elsewhere. A security administrator sees a colleague's card read-only, captioned for someone else and naming who can change it. The gates are aiCallsView (self or MANAGE_MEMBER_SECURITY, on a saved person who is a team member) and aiCallsEdit (the person themself), with a palette row.

  25. · SecurityService

    The team sub-resources (members, rights, roles) and the recalculation endpoint (KamoCollab CP01 T11)

    GET|PUT **************** /rights and /roles, and POST **************** (spec §5.7). Reads are open to any session of the org; writes need CONFIGURE_SYSTEM or an open god window, checked before the team is looked up. Each PUT replaces its one required list through TeamWriter, runs TeamService.afterWrite and answers the list as it now reads with rightsRecalculated: members recalculates who joined and who left only, rights and roles the team's members. The recalculation answers {recalculated: n}, the member count, and a failure is a 500 that leaks nothing.

  26. · kamo-internal

    SP96 the AI voice card on the profile, and the charter's VOICE section without the TTS pin

    An AI member's Identity room gains its voice card: one line per speech model it may use, in the order it tries them, with the voice it speaks there now and how it was chosen, the model used first, a model with no voice of its sex, and a voice that changes the next time it speaks, with why. A viewer AIService lets change it chooses another voice (a dialog of the voices that suit it) or the model used first; both save at once through the new BFF relays of AIService's member voice endpoints. The card reads its voices again when the saved sex changes. Its gate, aiVoiceView, is AIService's read rule, and it has a palette row. The charter editor's VOICE section is style text only: the TTS picker and the charter voice catalogue (client call and BFF route) are gone, the section says the voice is chosen on the profile, and an item still carrying a voice pin is flagged as shared-lib refuses it.

  27. · kamo-internal

    SP96 the AI voice card on the profile, and the charter's VOICE section without the TTS pin

    An AI member's Identity room gains its voice card: one line per speech model it may use, in the order it tries them, with the voice it speaks there now and how it was chosen, the model used first, a model with no voice of its sex, and a voice that changes the next time it speaks, with why. A viewer AIService lets change it chooses another voice (a dialog of the voices that suit it) or the model used first; both save at once through the new BFF relays of AIService's member voice endpoints. The card reads its voices again when the saved sex changes. Its gate, aiVoiceView, is AIService's read rule, and it has a palette row. The charter editor's VOICE section is style text only: the TTS picker and the charter voice catalogue (client call and BFF route) are gone, the section says the voice is chosen on the profile, and an item still carrying a voice pin is flagged as shared-lib refuses it.

  28. · AIService

    The brief leads a team's purpose with the team's name (KamoCollab CP01 T17)

    A TEAM PURPOSE line now reads "As a member of the {title} team: ", after the job title, like the ROLE, DEPARTMENT and JOB_TITLE leads. VERSION stays (D19): no brief has a TEAM layer yet, so nothing needs to recompile.

  29. · SecurityService

    TeamController — list, create, read, update and delete (KamoCollab CP01 T10)

    GET|POST /api/security/teams and GET|PUT|DELETE /api/security/teams/{id} (spec §5.7). Every handler resolves the caller first (401 without an org); reads are open to any session of the org; writes need CONFIGURE_SYSTEM or an open god window (403 MISSING_RIGHT with requiredRight), checked before the team is looked up. A non-UUID path id, an unknown id and another org's team are all 404 TEAM_NOT_FOUND. A write runs in TeamWriter's transaction, then TeamService.afterWrite outside it; create and update answer {team (the detail, with charter items), rightsRecalculated}, delete {deleted: true, rightsRecalculated}. Refusals keep TeamErrors' body, charter refusals CharterErrors' shape, and a constraint the database enforces against a concurrent save is a 409 asking for a reload, not a 500.

  30. · MediaService

    The internal DM path goes through chat policy and the AI turn guard, and every chat line says who wrote it (KamoCollab CP00 T7)

    POST **************** now requires source MEMBER or SYSTEM (else 400 SOURCE_REQUIRED). A MEMBER line is checked by chat policy as a member's own send (open-then-send when no DM exists; the existing DM's guid for the ONE_WAY reply window), refused 403 CHAT_POLICY, and an AI sender's line is counted by the turn guard (429 AI_TURN_LIMIT). The AI's line to its own human supervisor is never counted, and passes the rules while protectManagerLine is on. A SYSTEM line (calendar notices) skips both. The handler opens no transaction: the turn limit is read first, then InternalDirectMessageWriter (@Transactional @RetryOnDbConflict) opens the DM, admits the turn, writes the line and prepares the fan-out; the announcement follows the commit. media_objs.source is written: MEMBER by member sends and Exec2Exec posts, SYSTEM by internal SYSTEM lines and the Exec2Exec welcome, SERVICE by alerts. A SYSTEM or SERVICE line is not a human turn, so it no longer resets the AI counter. The fan-out frames, the send response, its NATS frame and history rows carry source (MEMBER for a NULL row).

Your universe is waiting.

Start free in minutes. Add products whenever you are ready — no migration, no new logins.

Free forever — no credit card required