Module: Karst::Access::ApprovedPopulations

Defined in:
lib/karst/access/approved_populations.rb

Overview

Turns locally approved candidate populations (see Karst::Access::PopulationApprovals) back into ordinary Karst::Access::PrincipalSource populations, so that everything downstream -- Access::Search, the panel, bin/rails karst:verify, the MCP verify_access tool -- keeps reading exactly one source of truth (Configuration#principal_sources) and needs to know nothing about approval at all.

Three independent conditions must hold before an approved entry becomes executable, and any one of them failing silently drops it:

1. Karst is running in a local development/test environment. An
 approval file that reaches production (committed by accident,
 copied into an image) approves nothing there.
2. The entry's model name matches the Active Record class of an
 already-configured (or inferred) principal source. The class is
 taken from that source -- never looked up, constantized, or loaded
 from the stored name -- so approval can only ever widen sampling
 within a model the application already pointed Karst at.
3. Current source-based discovery still confirms that exact
 zero-argument `scope` declaration on that class. A scope that was
 removed, renamed, or given parameters stops being executed the
 moment the source changes, with no file edit required, and a
 hand-written entry naming an arbitrary class method is never
 confirmed in the first place.

Explicit configuration always wins: a population name a source already configures is never replaced or duplicated by an approved entry of the same name, and configured populations keep their configured order ahead of approved ones (see Access::Search, which tries them in exactly this order).

Class Method Summary collapse

Class Method Details

.local_environment?Boolean

Karst's local approval workflow is a development affordance and nothing else. Test is included so an application's own test suite (and Karst's) can exercise it; every other environment, production included, ignores the file entirely.

Returns:

  • (Boolean)


82
83
84
85
86
87
# File 'lib/karst/access/approved_populations.rb', line 82

def local_environment?
  return false unless defined?(Rails) && Rails.respond_to?(:env)

  env = Rails.env
  env.respond_to?(:development?) && (env.development? || env.test?)
end

.merge(sources) ⇒ Object

Returns a Hash of the same shape it was given, with each source's populations extended by whatever its model has approved and confirmed. Returns the argument untouched when nothing applies, so the overwhelmingly common "no approvals" case costs one file stat.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/karst/access/approved_populations.rb', line 45

def merge(sources)
  return sources unless sources && local_environment?

  record = PopulationApprovals.load
  return sources if record.entries.empty?

  discovery = PopulationDiscovery.new
  sources.each_with_object({}) do |(name, source), merged|
    merged[name] = extend_source(source, record.entries, discovery)
  end
rescue StandardError
  # Approval is an optional convenience layered over configuration
  # Karst already had. If resolving it fails for any reason, the
  # honest degradation is "explicitly configured populations only" --
  # never a broken panel, CLI, or MCP tool.
  sources
end

.stale(sources, record: PopulationApprovals.load, discovery: PopulationDiscovery.new) ⇒ Object

Every approved entry that is not currently confirmed for any of the given sources, as [Entry, reason] pairs -- the honest "this approval exists but does nothing" list the panel shows. Never executes anything.



67
68
69
70
71
72
73
74
75
76
# File 'lib/karst/access/approved_populations.rb', line 67

def stale(sources, record: PopulationApprovals.load, discovery: PopulationDiscovery.new)
  klasses = source_klasses(sources)
  record.entries.filter_map do |entry|
    klass = klasses[entry.model_name]
    next [entry, :no_principal_source] unless klass
    next [entry, :not_discovered] unless discovery.confirms?(klass: klass, method_name: entry.method_name)

    nil
  end
end