Class: Insika::Server::AppBuilder
- Inherits:
-
Object
- Object
- Insika::Server::AppBuilder
- Defined in:
- lib/insika/server/rack_app.rb
Overview
Assembles Server::App from a graph. Also answers the two questions the boot
banner asks (workflows?/channels?), so registering the env channels
happens exactly once and in one place.
Instance Attribute Summary collapse
-
#criterion ⇒ Object
readonly
the frozen criterion, memoized when the relay runs in shadow — nil otherwise.
-
#graph ⇒ Object
readonly
Returns the value of attribute graph.
-
#token ⇒ Object
readonly
Returns the value of attribute token.
Instance Method Summary collapse
- #app ⇒ Object
-
#channels? ⇒ Boolean
Registers the env-configured channels once, and reports whether any exist.
-
#initialize(handle, token: nil, **config) ⇒ AppBuilder
constructor
Fixed local token: gates /v1 (Bearer) — and, under
serve, logs into the Studio (cookie). - #workflows? ⇒ Boolean
Constructor Details
#initialize(handle, token: nil, **config) ⇒ AppBuilder
Fixed local token: gates /v1 (Bearer) — and, under serve, logs into the
Studio (cookie). Never a real secret; override with token:/ADMIN_TOKEN.
37 38 39 40 41 42 |
# File 'lib/insika/server/rack_app.rb', line 37 def initialize(handle, token: nil, **config) @rt = handle.respond_to?(:runtime) ? handle.runtime : handle @graph = @rt.graph @token = token || ENV.fetch("ADMIN_TOKEN", "local-demo") @config = config end |
Instance Attribute Details
#criterion ⇒ Object (readonly)
the frozen criterion, memoized when the relay runs in shadow — nil otherwise. Loaded ONCE at boot (the refusal below), then shared.
48 49 50 |
# File 'lib/insika/server/rack_app.rb', line 48 def criterion @criterion end |
#graph ⇒ Object (readonly)
Returns the value of attribute graph.
45 46 47 |
# File 'lib/insika/server/rack_app.rb', line 45 def graph @graph end |
#token ⇒ Object (readonly)
Returns the value of attribute token.
44 45 46 |
# File 'lib/insika/server/rack_app.rb', line 44 def token @token end |
Instance Method Details
#app ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/insika/server/rack_app.rb', line 50 def app tenancy = @config[:tenancy] || ENV["INSIKA_TENANCY"] || "single_tenant" # WS1: the token store is handed over ONLY in multi_tenant mode — in # single_tenant the classic gateway token is the only credential # (passing the store would silently widen the surface). store = tenancy == "multi_tenant" ? @graph.token_store : nil @app ||= Insika::Server::App.new( command_bus: @graph.bus, event_stream: @graph.event_stream, session_store: @graph.session_store, task_store: @graph.task_store, pending_action_store: @graph.pending_action_store, provisioner: Insika::PackImporter.new(bus: @graph.bus, profiles: @graph.profiles), # GET /v1/agents/:id — the read-only capability view a case's `requires` # resolves against. profiles: @graph.profiles, # the OSS onboarding surface (start.md + models.json + docs). # This is the primary "build my first agent" target — models.json reports the # DSL's stores + the agents this process serves (each id IS the `model`). onboarding: build_onboarding, # GET /v1/workflows + POST /v1/workflows/:name, opt-in by # injection like every other edge — nil when the system declares none, # so the routes simply do not exist (404, parity). workflow_registry: (@graph.workflow_registry if workflows?), # the bundled relay, when the env turns it on. Same rule as the # OTEL bridge — a feature only `config.ru` can reach is a feature the # docs are half-true about. channels: (@graph.channel_registry if channels?), config: { gateway_token: @token, tenancy: tenancy }.merge(@config), token_store: store, outcome_store: @graph.outcome_store, # a 500's error_ref must be findable in the process log. logger: $stdout ) end |
#channels? ⇒ Boolean
Registers the env-configured channels once, and reports whether any exist.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/insika/server/rack_app.rb', line 87 def channels? unless defined?(@channels_ready) @channels_ready = true relay = Insika::Channels::Relay.from_env( http: Insika::HttpClient.new, allow_http: Insika::EnvSchema.truthy?(ENV["INSIKA_EGRESS_ALLOW_HTTP"]), allow_private: Insika::EnvSchema.truthy?(ENV["INSIKA_EGRESS_ALLOW_PRIVATE"]) ) # NO criterion, no shadow — enforced at boot, not per # turn. Raises ConfigError when the file is missing, unparseable, or # incomplete; the criterion is memoized here and injected into # ChannelDelivery (its sha stamps every pair our half records). if relay&.shadow? criterion_path = Insika::EnvSchema.read("INSIKA_PARITY_CRITERION") raise Insika::ConfigError, "shadow mode requires INSIKA_PARITY_CRITERION (the frozen criterion)" if criterion_path.nil? @criterion = Insika::Parity::Criterion.load(criterion_path) @graph.channel_delivery&.criterion_sha = @criterion.sha end @graph.channel_registry.register(relay.id, relay) if relay = Insika::Channels::Web.from_env( chat_rate_limit: Insika::Channels::Web.limit_resolver( profiles: @graph.profiles, settings_store: @rt.component(:settings_store) ) ) @graph.channel_registry.register(.id, ) if end !@graph.channel_registry.names.empty? end |
#workflows? ⇒ Boolean
84 |
# File 'lib/insika/server/rack_app.rb', line 84 def workflows? = !@graph.workflow_registry.names.empty? |