Commit 4b7cb45
release: v0.2.0 — frontend rewrite, ActiveMQ detector, mode=none default, drill-down treemap (#112)
* perf(detectors): quick-reject pre-screen on auth detectors (-31% detector CPU)
Profiling on a 30K-file polyglot fixture (kept at ~/projects/polyglot-bench:
spring-petclinic-microservices, airflow, istio, eShop, angular/components,
nuxt, actix/examples, ktor-samples, nlohmann/json, play-samples,
PSScriptAnalyzer, terraform-aws-eks; 14 distinct languages) showed the three
cross-cutting auth detectors burning 55% of all detector CPU because they
ran the lines × patterns double loop on every supported-language file —
even files with zero auth keywords.
Fix: per-detector PRE_SCREEN Pattern with all distinctive literal substrings
of the underlying patterns. One regex pass over file content; if no keyword
present, the file cannot match — short-circuit before the line loop.
Measured impact (JFR ExecutionSample, JDK 25, polyglot fixture):
CertificateAuthDetector: 244 → 147 samples (-39.8%, -0.97s CPU)
SessionHeaderAuthDetector: 206 → 43 samples (-79.1%, -1.63s CPU)
LdapAuthDetector: 47 → 25 samples (-46.8%, -0.22s CPU)
Auth subtotal: 497 → 215 samples (-56.7%, -2.82s)
All detectors total: 902 → 624 samples (-30.8%, -2.78s)
Detection semantics unchanged — pre-screen rejects only files where no
underlying pattern can match (keyword absent). Tests covering keyword-bearing
fixtures pass through pre-screen and run the existing logic byte-for-byte.
Tests: 3689 / 0 failures / 0 errors / 32 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(ui): migrate frontend from AntD to @ossrandom/design-system
Full UI rewrite onto @ossrandom/design-system v0.3.0 (npm). Replaces
Ant Design + ECharts + @ant-design/icons with the design-system
primitives + charts subpath + an inline-SVG icon set.
Surface changes:
- AppShell-based header with a single IconButton theme toggle and a
monospace MCP-URL pill (copy-to-clipboard).
- Stats grid replaced with a CSS auto-fit grid (mobile-responsive).
- File-tree treemap renders via @ossrandom/design-system/charts
(d3-hierarchy, canvas engine, maxDepth=1) with an explicit drill-down
/ drill-up affordance via a breadcrumb row; treemap layout is
deterministic (children sorted alphabetically, fixed height, single
remount via key when focusPath changes).
- File viewer drawer kept; MCP Tools sidebar removed (the design-system
Menu's nested-inline expansion didn't match the prior UX).
- Three orphan pages deleted (Explorer.tsx, McpConsole.tsx,
CodebaseMap.tsx) — none were routed in App.tsx.
- index.css trimmed to body reset + layout-only classes using
design-system CSS tokens; `.rcs-treemap-engine-badge` hidden via a
single rule.
- vite.config.ts: manualChunks reorganised
(vendor-ds / vendor-ds-charts replace vendor-antd / vendor-echarts).
Bundled fonts and the deck.gl tesselator chunk live alongside the
hashed JS in src/main/resources/static/assets/ — air-gapped requirement
per build.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(auth): allow_unauthenticated bypass actually grants /api access
When `mcp.auth.mode=none` AND `allow_unauthenticated=true`, the filter
used to call chain.doFilter(...) without setting an Authentication on
the SecurityContext. The SecurityFilterChain has
.requestMatchers("/api/**", "/mcp/**", "/actuator/**").authenticated()
.anonymous().disable()
so requests reaching the controllers without a Principal were rejected
with 403 — the "unauthenticated" escape hatch was inert. Bypass branch
now installs a fake PreAuthenticatedAuthenticationToken with role
ROLE_MCP_CLIENT (mirroring the bearer-success path) and clears the
context in finally, so the chain's authenticated() rule passes.
Behavioural impact only when allow_unauthenticated=true; bearer mode
unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(auth)!: default mcp.auth.mode=none with allow_unauthenticated=true
Built-in defaults now produce a server that starts unauthenticated out
of the box. The fail-fast safety valve still works: explicitly setting
mcp.auth.allow_unauthenticated=false in codeiq.yml (or env) makes
mode=none refuse to start under the serving profile.
ConfigDefaults previously emitted
new McpAuthConfig("none", "CODEIQ_MCP_TOKEN", null, null)
which evaluated to allowUnauthenticated=false at runtime; combined with
TokenResolver's serving-profile gate, this hard-failed every fresh
install on `codeiq serve`. Operators wanting auth in production opt in
explicitly via mode=bearer (and CODEIQ_MCP_TOKEN env var).
McpAuthConfig javadoc updated to document the new default semantics:
allow_unauthenticated is now an opt-in *harden* flag (set false to
reject mode=none) rather than an opt-in *escape hatch*.
BREAKING (defaults): a fresh install no longer prompts for or enforces
a token. Upgraded deployments that already set mode=bearer in
codeiq.yml are unaffected. To preserve the prior fail-fast behaviour,
set mcp.auth.allow_unauthenticated: false explicitly.
Tests: TokenResolverTest, ConfigDefaultsTest, ServingChainIntegrationTest,
UnifiedConfigAdapterTest — 27/27 pass. Full suite: 3706 / 0 / 32.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(messaging): Apache ActiveMQ Classic + Artemis detector
Adds io.github.randomcodespace.iq.detector.jvm.java.ActiveMqDetector
covering both ActiveMQ Classic (org.apache.activemq.*) and ActiveMQ
Artemis (org.apache.activemq.artemis.*). Both products ship a class
literally named ActiveMQConnectionFactory, so the broker flavour is
disambiguated by import / FQN before emission.
Coverage:
- Connection factories: ActiveMQConnectionFactory,
ActiveMQQueueConnectionFactory, ActiveMQTopicConnectionFactory,
ActiveMQJMSConnectionFactory, ActiveMQXAConnectionFactory,
PooledConnectionFactory.
- Transport URLs: tcp/ssl/nio/udp/vm/amqp/stomp/mqtt/ws/wss with the
optional +nio / +ssl modifiers, plus failover:(...) / failover:tcp:...
(the failover transport uses `:(` rather than `://`, handled as a
separate alternation in BROKER_URL_RE).
- Direct destination instantiation: new ActiveMQQueue("..."),
new ActiveMQTopic("...").
- session.createQueue("...") / session.createTopic("...") only
attributed to ActiveMQ when the file already mentions an AMQ import
or class ref — avoids double-counting against JmsDetector.
- Spring Boot config keys: spring.activemq.broker-url and
spring.artemis.broker-url in application.properties / application.yml
(no class context — emits the broker MESSAGE_QUEUE node only).
Emits NodeKind {MESSAGE_QUEUE, QUEUE, TOPIC} with broker properties
("activemq" or "activemq_artemis"), plus EdgeKind
{CONNECTS_TO, SENDS_TO, RECEIVES_FROM} — same shape as IbmMqDetector
and TibcoEmsDetector so the topology view composes cleanly.
Tests: 17 cases covering metadata, early-exit, Classic + Artemis,
named queue/topic producer/consumer, transport URL variants
(failover, pooled), Spring Boot config keys, negative
double-counting against JmsDetector, and a determinism fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(health): make `codeiq serve` start cleanly under Spring Boot 4
Two coupled changes that together let `serve` boot from defaults
without -D / env / config overrides.
1. GraphHealthIndicator: @ConditionalOnBean(GraphStore.class) →
@Profile("serving"). Spring documents @ConditionalOnBean as fragile
on user @component classes (its evaluation depends on bean-definition
ordering during scan). The serving profile already guarantees
GraphStore is present; @Profile activates earlier and deterministic-
ally so the readiness-group reference resolves on a clean install.
2. application.yml: management.endpoint.health.validate-group-membership
set to false. Spring Boot 4 enabled strict group-membership validation
by default — startup fails when a `health.group.*.include` references
a profile-conditional bean that hasn't yet been added to the registry
when the management endpoint config loads. The serving profile's
readiness include of `graphHealthIndicator` consistently tripped this.
Disabled per the error message's own remediation hint; missing health
contributors are silently skipped at probe time, which is the desired
runtime behaviour.
Verified: `java -jar code-iq-cli.jar serve <path> -p 37779` with no
flags / env / codeiq.yml — port binds, /api/stats returns data without
auth, /actuator/health/readiness returns {"status":"UP"}.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(build): regenerate package-lock.json against npm registry
The previous lockfile pointed @ossrandom/design-system at a local
filesystem path (`file:../../../../design-system`, link:true) — a
holdover from the local-checkout development of the design-system.
On CI that path doesn't exist, so `npm install` left the dep
unresolved and `vite build` failed with TS2307 "Cannot find module
'@ossrandom/design-system'".
Regenerated lockfile resolves to the published 0.3.0 tarball:
https://registry.npmjs.org/@ossrandom/design-system/-/design-system-0.3.0.tgz
Verified locally: `rm -rf node_modules && npm install` clean,
`npm run build` produces the same bundle modulo content-hash filenames.
The two new design-system-*.js chunks reflect the registry-resolved
artifact.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 3bc3ebf commit 4b7cb45
24 files changed
Lines changed: 3269 additions & 2669 deletions
File tree
- src
- main
- frontend
- src
- components
- pages
- java/io/github/randomcodespace/iq
- config
- security
- unified
- detector/jvm/java
- health
- resources
- static/assets
- test/java/io/github/randomcodespace/iq/detector/jvm/java
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
| 15 | + | |
| 16 | + | |
19 | 17 | | |
20 | 18 | | |
21 | 19 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
3 | | - | |
| 2 | + | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
7 | 14 | | |
8 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
9 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
10 | 79 | | |
| 80 | + | |
11 | 81 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
| 82 | + | |
| 83 | + | |
41 | 84 | | |
42 | | - | |
43 | | - | |
| 85 | + | |
| 86 | + | |
44 | 87 | | |
45 | 88 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 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 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 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 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
14 | 134 | | |
0 commit comments