ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / internal/modules/collab/service.go

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / internal/modules/collab/service.go
DateNot specified in source
RepositoryJanady13/missionmatch
Revision720d47fae476b0d38477ae4401697d372b1ea2bc
Branchfeature/opportunity-to-outcome
Path or archive memberinternal/modules/collab/service.go
Original SHA-25649aec87de71fdcf0a2a8160e540381ae88ac1a659995c7e95218d9bf28b25d55
Git blob SHA18a527ed0e6d831398a2e0b513148741b5e45fb5
Reading-copy SHA-25649aec87de71fdcf0a2a8160e540381ae88ac1a659995c7e95218d9bf28b25d55

Original source ↗

Recovered source transcript

// Package collab answers one question a recruiting floor asks all day: is anybody already on this. // // WHY IT IS ITS OWN MODULE. The question is identical for a candidate, a requisition, an opportunity, a // proposal and a client, and the answer has to look the same for all of them. Putting it in the recruiting // module would have made the missionmatch module import a sibling to ask about a candidate; putting a copy in // each would have produced five answers that drift. // // IT IS NOT A SECOND OWNERSHIP SYSTEM. clients and requisitions have carried owner_user_id since migration // 0047, with claim and reassign in internal/modules/recruiting/ownership.go, and that column stays // authoritative for whose desk a record belongs to. A claim here is shorter lived and answers something // else: not "this account is mine" but "I am on this right now, do not also call them today". The read // surface returns BOTH, because a candidate sitting on Dana's desk while Marcus submits them this afternoon // is two true facts and a recruiter needs each. CANDIDATES have neither today, and a candidate phoned twice // in one day by the same agency is the complaint this closes. // // A CLAIM IS NOT A LOCK. Claims expire, and claim_required is off by default. Even with it on, a second // person is warned rather than blocked, because an agency that cannot move a desk at five o'clock on a // deadline day loses the award. The product's job here is to make the collision VISIBLE, not to arbitrate it. package collab import ( "context" "errors" "fmt" "strings" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/missionworkforce/missionmatch/internal/platform/audit" "github.com/missionworkforce/missionmatch/internal/platform/orgsettings" "github.com/missionworkforce/missionmatch/internal/platform/security" "github.com/missionworkforce/missionmatch/internal/platform/tenant" ) var ( ErrNoDatabase = errors.New("collab: no database configured") ErrUnknownType = errors.New("collab: unknown entity type") ErrNotFound = errors.New("collab: no such record in this organization") ErrClaimedByOther = errors.New("collab: someone else already holds a live claim on this record") ErrNotYours = errors.New("collab: that claim belongs to someone else") ) // entityTables maps the closed vocabulary the database CHECK already enforces onto the table each type lives // in. IT IS A CLOSED MAP AND THAT IS THE POINT: the table name is interpolated into SQL, so it may only ever // come from here, never from a request. A caller supplying an unknown type gets ErrUnknownType before any // query is built. var entityTables = map[string]string{ "candidate": "candidates", "requisition": "requisitions", "opportunity": "opportunities", "proposal": "proposals", "client": "clients", } // ownerColumns names the types that ALSO carry desk ownership, so the read can return the existing // owner_user_id alongside the claim rather than pretending claims are the only notion of who has this. var ownerColumns = map[string]string{ "requisition": "owner_user_id", "client": "owner_user_id", } func ValidEntityType(t string) bool { _, ok := entityTables[t]; return ok } type Service struct { db *tenant.DB settings *orgsettings.Store aud *audit.Writer clock func() time.Time } func NewService(db *tenant.DB, settings *orgsettings.Store, aud *audit.Writer) *Service { return &Service{db: db, settings: settings, aud: aud, clock: time.Now} } // Claim is one person saying they are working a record now. type Claim struct { ID string `json:"id"` EntityType string `json:"entity_type"` EntityID string `json:"entity_id"` UserID string `json:"user_id"` UserName string `json:"user_name"` Activity string `json:"activity"` Note string `json:"note"` ClaimedAt time.Time `json:"claimed_at"` ExpiresAt time.Time `json:"expires_at"` ReleasedAt *time.Time `json:"released_at,omitempty"` // Mine lets the interface show "you have this" without comparing identifiers in the browser. Mine bool `json:"mine"` } // Touch is the soft signal: somebody looked at this recently. type Touch struct { UserID string `json:"user_id"` UserName string `json:"user_name"` LastSeenAt time.Time `json:"last_seen_at"` Mine bool `json:"mine"` } // Activity is the whole answer for one record: who owns the desk, who is on it now, and who has looked at it // lately, already filtered by what this caller is allowed to see. type Activity struct { EntityType string `json:"entity_type"` EntityID string `json:"entity_id"` Claim *Claim `json:"claim"` Touches []Touch `json:"touches"` // DeskOwner is the existing owner_user_id from migration 0047 where the entity type has one. It is a // DIFFERENT fact from Claim and both are returned deliberately. DeskOwnerUserID string `json:"desk_owner_user_id,omitempty"` DeskOwnerName string `json:"desk_owner_name,omitempty"` // Visible reports whether this caller may see other people's activity at all. When it is false the // claim and touch lists carry only the caller's OWN entries, never a silently empty answer that would // read as "nobody is on this". Visible bool `json:"visible_to_you"` // ClaimRequired mirrors the organization's setting so the interface can warn before a second person // starts work. It is a warning, never a block. ClaimRequired bool `json:"claim_required"` } // ClaimInput is a request to take a record. type ClaimInput struct { Activity string `json:"activity"` Note string `json:"note"` // Steal takes a record that somebody else holds. It is explicit, audited, and never implicit, so the // trail distinguishes a colleague coordinating from a record changing hands behind someone's back. Steal bool `json:"steal"` } var validActivities = map[string]bool{ "working": true, "screening": true, "submitting": true, "interviewing": true, "negotiating": true, } // TakeClaim records that the caller is working this record. func (s *Service) TakeClaim(ctx context.Context, entityType string, entityID uuid.UUID, in ClaimInput, ip, ua string) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } if !ValidEntityType(entityType) { return Activity{}, ErrUnknownType } actor, ok := tenant.UserFromContext(ctx) if !ok { return Activity{}, tenant.ErrNoTenant } actorID, err := uuid.Parse(actor.UserID) if err != nil { return Activity{}, tenant.ErrNoTenant } if in.Activity == "" { in.Activity = "working" } if !validActivities[in.Activity] { return Activity{}, fmt.Errorf("collab: %q is not a recognised activity", in.Activity) } if len(in.Note) > 280 { in.Note = in.Note[:280] } var out Activity err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { // The record must exist IN THIS TENANT. The query runs under RLS, so a record belonging to another // organization simply is not there, and the caller learns nothing about whether it exists elsewhere. if e := assertExists(ctx, tx, entityType, entityID); e != nil { return e } st, e := s.settings.LoadTx(ctx, tx) if e != nil { return e } // EXPIRED CLAIMS ARE RELEASED FIRST. The unique index that makes "who is on this" a single row // answer covers every unreleased claim, expired or not, so without this an abandoned claim would own // a candidate forever and no one could take it. if _, e := tx.Exec(ctx, ` UPDATE work_claims SET released_at = now() WHERE entity_type = $1 AND entity_id = $2 AND released_at IS NULL AND expires_at <= now()`, entityType, entityID); e != nil { return e } var holder uuid.UUID e = tx.QueryRow(ctx, ` SELECT user_id FROM work_claims WHERE entity_type = $1 AND entity_id = $2 AND released_at IS NULL`, entityType, entityID).Scan(&holder) switch { case e != nil && !errors.Is(e, pgx.ErrNoRows): return e case e == nil && holder == actorID: // Already theirs. Extend it rather than refusing, because a recruiter pressing claim again means // "I am still on this", which is exactly what the expiry needs to hear. _, e = tx.Exec(ctx, ` UPDATE work_claims SET expires_at = now() + make_interval(hours => $1), activity = $2, note = CASE WHEN $3 = '' THEN note ELSE $3 END WHERE entity_type = $4 AND entity_id = $5 AND released_at IS NULL`, st.ClaimExpiryHours, in.Activity, in.Note, entityType, entityID) if e != nil { return e } out, e = s.activityTx(ctx, tx, entityType, entityID, actorID, security.Role(actor.Role), st) return e case e == nil && !in.Steal: return ErrClaimedByOther case e == nil && in.Steal: if _, e := tx.Exec(ctx, ` UPDATE work_claims SET released_at = now(), released_by = $1 WHERE entity_type = $2 AND entity_id = $3 AND released_at IS NULL`, actorID, entityType, entityID); e != nil { return e } // A takeover is audited on its own, separately from the claim, because "Marcus took this from // Dana" is the event a manager needs to be able to find later. if s.aud != nil { body, _ := marshalJSON(map[string]any{ "entity_type": entityType, "entity_id": entityID.String(), "taken_from": holder.String(), "taken_by": actorID.String(), }) if e := s.aud.OnTx(ctx, tx, audit.Event{ Action: "work.claim.taken_over", ActorUserID: &actorID, EntityType: entityType, EntityID: entityID.String(), NewValues: body, IPAddress: ip, UserAgent: ua, }); e != nil { return e } } } if _, e := tx.Exec(ctx, ` INSERT INTO work_claims (organization_id, entity_type, entity_id, user_id, activity, note, expires_at) VALUES (NULLIF(current_setting('app.current_org_id', true), '')::uuid, $1, $2, $3, $4, $5, now() + make_interval(hours => $6))`, entityType, entityID, actorID, in.Activity, in.Note, st.ClaimExpiryHours); e != nil { return e } out, e = s.activityTx(ctx, tx, entityType, entityID, actorID, security.Role(actor.Role), st) return e }) return out, err } // ReleaseClaim gives a record back. A manager may release somebody else's, because a recruiter who leaves at // lunch and does not come back must not hold a candidate until the expiry runs out. func (s *Service) ReleaseClaim(ctx context.Context, entityType string, entityID uuid.UUID, ip, ua string) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } if !ValidEntityType(entityType) { return Activity{}, ErrUnknownType } actor, ok := tenant.UserFromContext(ctx) if !ok { return Activity{}, tenant.ErrNoTenant } actorID, err := uuid.Parse(actor.UserID) if err != nil { return Activity{}, tenant.ErrNoTenant } role := security.Role(actor.Role) isManager := security.AtLeast(role, security.RoleManager) var out Activity err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { var holder uuid.UUID e := tx.QueryRow(ctx, ` SELECT user_id FROM work_claims WHERE entity_type = $1 AND entity_id = $2 AND released_at IS NULL`, entityType, entityID).Scan(&holder) if errors.Is(e, pgx.ErrNoRows) { // Releasing a record nobody holds is not an error. It is the state the caller wanted. st, se := s.settings.LoadTx(ctx, tx) if se != nil { return se } out, se = s.activityTx(ctx, tx, entityType, entityID, actorID, role, st) return se } if e != nil { return e } if holder != actorID && !isManager { return ErrNotYours } if _, e := tx.Exec(ctx, ` UPDATE work_claims SET released_at = now(), released_by = $1 WHERE entity_type = $2 AND entity_id = $3 AND released_at IS NULL`, actorID, entityType, entityID); e != nil { return e } if s.aud != nil && holder != actorID { body, _ := marshalJSON(map[string]any{ "entity_type": entityType, "entity_id": entityID.String(), "released_holder": holder.String(), "released_by": actorID.String(), }) if e := s.aud.OnTx(ctx, tx, audit.Event{ Action: "work.claim.released_by_manager", ActorUserID: &actorID, EntityType: entityType, EntityID: entityID.String(), NewValues: body, IPAddress: ip, UserAgent: ua, }); e != nil { return e } } st, se := s.settings.LoadTx(ctx, tx) if se != nil { return se } out, se = s.activityTx(ctx, tx, entityType, entityID, actorID, role, st) return se }) return out, err } // Touch records that the caller looked at a record, and returns the activity they are allowed to see. This is // the call a detail screen makes on open: it is both the write and the read, so a page load is one request. // // IT IS AN UPSERT, NEVER AN APPEND. One row per person per record. Appending would generate a row per page // view per recruiter per candidate, which is millions of rows a month describing something nobody reads // twice, and it would put a browsing history of a named employee in a trivially reportable table. This is // presence, not surveillance. func (s *Service) Touch(ctx context.Context, entityType string, entityID uuid.UUID) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } if !ValidEntityType(entityType) { return Activity{}, ErrUnknownType } actor, ok := tenant.UserFromContext(ctx) if !ok { return Activity{}, tenant.ErrNoTenant } actorID, err := uuid.Parse(actor.UserID) if err != nil { return Activity{}, tenant.ErrNoTenant } var out Activity err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { if e := assertExists(ctx, tx, entityType, entityID); e != nil { return e } st, e := s.settings.LoadTx(ctx, tx) if e != nil { return e } // Presence is only recorded when the organization wants it. An organization that switched it off is // asking not to be tracked, and writing the row anyway and merely hiding it would be a lie. if st.ShowActivityPresence { if _, e := tx.Exec(ctx, ` INSERT INTO work_touches (organization_id, entity_type, entity_id, user_id, last_seen_at) VALUES (NULLIF(current_setting('app.current_org_id', true), '')::uuid, $1, $2, $3, now()) ON CONFLICT (organization_id, entity_type, entity_id, user_id) DO UPDATE SET last_seen_at = now()`, entityType, entityID, actorID); e != nil { return e } } out, e = s.activityTx(ctx, tx, entityType, entityID, actorID, security.Role(actor.Role), st) return e }) return out, err } // GetActivity reads without recording a visit. func (s *Service) GetActivity(ctx context.Context, entityType string, entityID uuid.UUID) (Activity, error) { if s.db == nil { return Activity{}, ErrNoDatabase } if !ValidEntityType(entityType) { return Activity{}, ErrUnknownType } actor, ok := tenant.UserFromContext(ctx) if !ok { return Activity{}, tenant.ErrNoTenant } actorID, err := uuid.Parse(actor.UserID) if err != nil { return Activity{}, tenant.ErrNoTenant } var out Activity err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { if e := assertExists(ctx, tx, entityType, entityID); e != nil { return e } st, e := s.settings.LoadTx(ctx, tx) if e != nil { return e } out, e = s.activityTx(ctx, tx, entityType, entityID, actorID, security.Role(actor.Role), st) return e }) return out, err } // MyClaims is the recruiter's own list, which is the other half of not double working: knowing what you // yourself have open. It is never filtered by visibility, because these are the caller's own claims. func (s *Service) MyClaims(ctx context.Context) ([]Claim, error) { if s.db == nil { return nil, ErrNoDatabase } actor, ok := tenant.UserFromContext(ctx) if !ok { return nil, tenant.ErrNoTenant } actorID, err := uuid.Parse(actor.UserID) if err != nil { return nil, tenant.ErrNoTenant } out := make([]Claim, 0, 32) err = s.db.RunInTenantTx(ctx, func(ctx context.Context, tx pgx.Tx) error { rows, e := tx.Query(ctx, ` SELECT c.id::text, c.entity_type, c.entity_id::text, c.user_id::text, coalesce(u.full_name,''), c.activity, c.note, c.claimed_at, c.expires_at FROM work_claims c LEFT JOIN users u ON u.id = c.user_id WHERE c.user_id = $1 AND c.released_at IS NULL AND c.expires_at > now() ORDER BY c.claimed_at DESC LIMIT 200`, actorID) if e != nil { return e } defer rows.Close() for rows.Next() { var c Claim if e := rows.Scan(&c.ID, &c.EntityType, &c.EntityID, &c.UserID, &c.UserName, &c.Activity, &c.Note, &c.ClaimedAt, &c.ExpiresAt); e != nil { return e } c.Mine = true out = append(out, c) } return rows.Err() }) return out, err } // activityTx assembles the answer and APPLIES THE VISIBILITY RULE. This is the one place that decides, so a // new caller cannot reach the raw rows and forget. func (s *Service) activityTx(ctx context.Context, tx pgx.Tx, entityType string, entityID, actorID uuid.UUID, role security.Role, st orgsettings.Settings) (Activity, error) { a := Activity{ EntityType: entityType, EntityID: entityID.String(), Touches: []Touch{}, Visible: security.CanSeeOthersWork(role, st.WorkVisibility), ClaimRequired: st.ClaimRequired, } var c Claim var released *time.Time err := tx.QueryRow(ctx, ` SELECT c.id::text, c.user_id::text, coalesce(u.full_name,''), c.activity, c.note, c.claimed_at, c.expires_at, c.released_at FROM work_claims c LEFT JOIN users u ON u.id = c.user_id WHERE c.entity_type = $1 AND c.entity_id = $2 AND c.released_at IS NULL AND c.expires_at > now()`, entityType, entityID).Scan(&c.ID, &c.UserID, &c.UserName, &c.Activity, &c.Note, &c.ClaimedAt, &c.ExpiresAt, &released) switch { case errors.Is(err, pgx.ErrNoRows): // No live claim, nothing to show or hide. case err != nil: return Activity{}, err default: c.EntityType, c.EntityID = entityType, entityID.String() c.Mine = c.UserID == actorID.String() // A caller who may not see other people's work still sees their OWN claim. Hiding it would leave a // recruiter unable to tell they already hold the record, which causes the very double work this is // here to prevent. if a.Visible || c.Mine { a.Claim = &c } } if st.ShowActivityPresence { rows, e := tx.Query(ctx, ` SELECT t.user_id::text, coalesce(u.full_name,''), t.last_seen_at FROM work_touches t LEFT JOIN users u ON u.id = t.user_id WHERE t.entity_type = $1 AND t.entity_id = $2 AND t.last_seen_at > now() - interval '24 hours' ORDER BY t.last_seen_at DESC LIMIT 25`, entityType, entityID) if e != nil { return Activity{}, e } defer rows.Close() for rows.Next() { var t Touch if e := rows.Scan(&t.UserID, &t.UserName, &t.LastSeenAt); e != nil { return Activity{}, e } t.Mine = t.UserID == actorID.String() if a.Visible || t.Mine { a.Touches = append(a.Touches, t) } } if rows.Err() != nil { return Activity{}, rows.Err() } } // Desk ownership, where the entity type has it. Read from the EXISTING column rather than duplicated // here, so migration 0047 stays the single source of truth for whose account this is. if col, ok := ownerColumns[entityType]; ok && a.Visible { var oid, oname *string q := fmt.Sprintf(`SELECT e.%s::text, u.full_name FROM %s e LEFT JOIN users u ON u.id = e.%s WHERE e.id = $1`, col, entityTables[entityType], col) if e := tx.QueryRow(ctx, q, entityID).Scan(&oid, &oname); e != nil && !errors.Is(e, pgx.ErrNoRows) { return Activity{}, e } if oid != nil { a.DeskOwnerUserID = *oid } if oname != nil { a.DeskOwnerName = *oname } } return a, nil } // assertExists proves the record is in THIS tenant before anything is written about it. Without it a claim // could be recorded against an identifier that does not exist, or one belonging to another organization, // producing rows that reference nothing and a presence list for a record the caller cannot see. func assertExists(ctx context.Context, tx pgx.Tx, entityType string, entityID uuid.UUID) error { table, ok := entityTables[entityType] if !ok { return ErrUnknownType } // The table name comes from the closed map above and can never be caller supplied. The identifier is a // bound parameter. var one int err := tx.QueryRow(ctx, fmt.Sprintf(`SELECT 1 FROM %s WHERE id = $1`, table), entityID).Scan(&one) if errors.Is(err, pgx.ErrNoRows) { return ErrNotFound } return err } // EntityTypes returns the vocabulary, for the handler's error messages and for tests. func EntityTypes() []string { out := make([]string, 0, len(entityTables)) for k := range entityTables { out = append(out, k) } // Sorted so the message is stable and a test can assert it. for i := 1; i < len(out); i++ { for j := i; j > 0 && out[j] < out[j-1]; j-- { out[j], out[j-1] = out[j-1], out[j] } } return out } func typeList() string { return strings.Join(EntityTypes(), ", ") }

Search equations, builds, manuscript text, and recovered sources.