name: module-architecture-boundaries description: Use when adding or refactoring EasyPostman modules, shared code, plugin contracts, UI utilities, i18n, settings, theme/font handling, or deciding where a class belongs.
Module Architecture Boundaries
Use this skill before adding shared code or moving code between modules. The goal is to keep EasyPostman's Maven modules small enough to reason about and strict enough that future changes do not turn into a catch-all common layer.
Source of truth
Read docs/ARCHITECTURE_MODULES_zh.md first when the task is about module placement, architecture cleanup, shared UI, plugin contracts, i18n, theme, font, settings, startup, update, welcome/help, request core, collection core, API core, or performance core.
Placement rules
Put non-UI base capabilities in
easy-postman-foundation. Examples: shared DTOs, enums, constants, config paths, JSON helpers, system utilities, user-setting helpers, i18n mechanism, base message keys, and generic parsing/formatting helpers such as Cron, JSON Path, XML, file-size, file-extension, time-display, and HTTP header constants.Put plugin extension contracts in
easy-postman-plugin-api. Examples:EasyPostmanPlugin,PluginContext,PluginDescriptor, service interfaces, toolbox/script/snippet contracts.Put request specification models in
easy-postman-request-core. Examples:HttpRequestItem,SavedResponse,HttpHeader,HttpParam,HttpFormData,HttpFormUrlencoded,CookieInfo, auth/body/protocol enums, redirect metadata, and transport-auth metadata. Keep it UI-free and transport-implementation-free: no Swing, OkHttp, app service/panel code, plugin runtime, or concrete send/render implementation.Put collection domain models and neutral import parsing in
easy-postman-collection-core. Examples:RequestGroup,CollectionNode,CollectionNodeType,CollectionParseResult, collection auth parsing helpers, and Postman collection parsing. Keep it UI-free and host-free: no Swing/AWT, OkHttp, app service/panel/runtime code, platform, plugin runtime, IOC, or concrete send/render implementation.Put HTTP transport runtime in
easy-postman-http-runtime. Examples:PreparedRequest,HttpResponse,HttpEventInfo, runtime settings/provider, OkHttp adapters, TLS/client certificate ports, Cookie store, SSE callbacks, redirect execution, UI-neutral interaction sinks, and network observation sinks. Keep it UI-free and host-free: no Swing/AWT, appSettingManager, app plugin-host accessors, panel code, platform IOC, or JavaFX/Swing-specific adapters.Put shared Swing design-system code in
easy-postman-ui. Examples:FontsUtil,IconUtil,NotificationCenter,EditorThemeUtil,ModernColors, reusable toolbar buttons/search/table/dialog/form controls such asEditButton,SaveButton,WrapToggleButton,EasyComboBox,EasyJSpinner,EasyPasswordField, and the icons/resources those reusable components directly reference. UI singleton framework classes such asUiSingletonFactory,UiSingletonPanel,UiSingletonMenuBar, plus Swing refresh/save helpers such asIRefreshableandDebouncedSaveSupport, also belong here. Generic action/control/status icons such as save, copy, paste, search, clear, cancel, close, delete, duplicate, eye, info, warning, arrows, chevrons, wrap, start, stop, send, connect, collapse, expand, more, detail, import, and export belong here. Do not duplicate the sameicons/*.svgresource path ineasy-postman-app, and do not make official plugins depend on app-only icon resources.Put plugin loading mechanics in
easy-postman-plugin-runtime. Examples: plugin scanning, descriptor parsing, classloaders, registry, lifecycle, disabled/uninstall state.Put performance domain core contracts in
easy-postman-performance-core: editable plan data, executableplan.json, runtime contracts, stats/report snapshots, worker assignments, and asset references. Keep concrete GUI/headless execution adapters ineasy-postman-appuntil the app execution semantics can be extracted without pulling in Swing, workspace services, or app-only state.Put host platform framework capabilities in
easy-postman-platformwhen they can be separated from concrete app UI. Current examples: the custom IOC container undercom.laker.postman.ioc, and update discovery core undercom.laker.postman.platform.update(version comparison, update source selection, asset resolution, changelog fetching/formatting, update result models). Future examples: startup orchestration, welcome/help, settings center, and theme/font application orchestration.Keep concrete host UI and composition in
easy-postman-app. Examples:App,MainFrame, menus, app-only panels, settings pages, update dialogs, update download/install/exit flow, welcome/help pages, and concrete startup wiring that still depends on app UI. Do not recreate a generic app model package for HTTP runtime exchange snapshots. Domain-specific app models should live with their owner package, such asfunctional.model,script.model,stream,snippet,history,certificate,variable,environment, orservice.curl.Keep HTTP request preparation adapters separated from HTTP transport runtime. Request preparation, validation, collection inheritance, variable resolution, scripts, and default request factories may stay in
easy-postman-app/http.requestwhile they still depend on app services. URL/query helpers belong in request-core. Transport execution belongs ineasy-postman-http-runtime. Swing implementations belong in UI adapters such ascom.laker.postman.panel.http.runtime, and app-specific runtime bootstrap belongs undercom.laker.postman.http.runtime.app.
Plugin Compatibility Boundary
Before removing, renaming, moving, or changing signatures/behavior for public types in modules that plugins may depend on, check whether old plugin JARs can still link against the new host. This includes easy-postman-plugin-api, easy-postman-foundation, and easy-postman-ui, because official and third-party plugins use them with provided scope.
Treat these as plugin-platform breaking changes:
- Deleting or renaming a public class, enum, method, constructor, field, package, resource path, or descriptor key that a plugin could reference.
- Changing method signatures, enum constants, constructor requirements, service contracts, extension-point semantics, or runtime loading behavior.
- Moving shared UI entry points such as notification, icon, color, font, or reusable component APIs without a binary-compatible facade.
When the change is intentionally incompatible, do all of this in the same patch:
- Bump root
pom.xmlplugin.platform.versionto the next incompatible platform version. Do not userevisionfor this. - Ensure official plugin
pom.xmlfiles resolveplugin.minPlatformVersionandplugin.maxPlatformVersionto the new platform version. If the plugins are rebuilt for the host release, update their plugin<version>andplugin.minAppVersionto the release they require. - Update plugin runtime/update tests so an old platform range, such as the previous
plugin.platform.version, is rejected before plugin code is loaded. - Do not edit existing catalog entries for already-published plugin JARs to claim a new platform range. Those entries are tied to their existing
sha256. New platform ranges belong to new rebuilt plugin artifacts generated by the plugin release workflow. If a catalog must be edited manually, update bothplugin-catalog/andeasy-postman-plugins/plugin-manager/src/main/resources/plugin-catalog/.
If preserving compatibility is the goal instead, keep a binary-compatible facade or overload with the old package/class/signature and add tests for old entry points. Do not bump plugin.platform.version for a compatible refactor.
Update Boundaries
- Put update discovery core in
platform:UpdateInfo,UpdateCheckFrequency,VersionChecker,VersionComparator,UpdateSourceSelector, release sources, asset resolvers, changelog service/formatter, and Windows registry/package-mode helpers. - Keep concrete update UX in
app:AppUpdateCheckCoordinator,UpdateUiController,UpdateDownloader, update dialogs/notifications, manual-download/open-browser commands, install prompts, and app shutdown for installation. platformupdate code must not import appSettingManager; inject a minimal provider such asUpdateSettingsProviderand adapt it in app withSettingManager::getUpdateSourcePreference.
I18n, Fonts, Theme
- I18n mechanism and cross-module generic labels belong in
foundation:I18nUtil,CommonI18n,CommonMessageKeys, andcommon-messages*. - I18n resources follow their owner: generic short labels such as OK, Cancel, Save, Copy, Close, Search, Success, Error, Warning, and Tip in foundation common bundles; shared UI component-specific strings in
ui(ui-messages*); host strings inapp(messages_*); plugin strings in each plugin. - Font helpers and typography rules belong in
ui; startup application of font settings belongs inplatformonce decoupled from app-specific wiring. - Theme tokens, semantic colors, icon color strategies, RSyntaxTextArea editor theme XMLs, and reusable UI resources belong in
ui; FlatLaf installation and theme switching belong inplatformonce decoupled from app-specific wiring. FlatLaf properties tied to app LAF classes can stay inappuntil those classes move. - Primary-color buttons must use on-primary icon color. Icons on blue/brand buttons stay white and must not switch with the light/dark theme foreground.
SVG Icon Guidance
README.mdandREADME_zh.mddeclare SVG icons are sourced from Lucide /lucide-icons/lucideunder the ISC license. For new or refreshed generic UI/action/sidebar icons, start from Lucide before inventing custom paths.- Keep single-color themeable SVGs as
viewBox="0 0 24 24",fill="none",stroke="currentColor",stroke-width="2",stroke-linecap="round", andstroke-linejoin="round"to match existing sidebar icons. - Use
IconUtil.createThemed(...)for neutral sidebar/status/tool icons so light and dark themes can recolor them. Use fixed-color SVGs orIconUtil.create(...)only for brand, protocol, or status assets that intentionally carry their own colors. - Resource ownership still applies: generic actions in
easy-postman-ui, app/domain icons in app, plugin icons in plugin resources. Do not duplicateicons/*.svgnames across modules.
Code Style And Testability
- Use Lombok for ordinary boilerplate when it makes code smaller and clearer:
@Slf4j,@RequiredArgsConstructor,@Getter/@Setter, model annotations, and@UtilityClassfor stateless static helpers. Avoid Lombok only when explicit code is clearer for Swing lifecycle, validation-heavy construction, or framework compatibility. - Do not add production hooks, injectable exits, extra state, or abstraction layers only to make a test possible if that makes the production code more complex. Prefer testing observable behavior through existing public/package APIs, focused static architecture tests, or a simpler production fix with a smaller test. Add a seam only when it also improves real design, not just test mechanics.
Anti-patterns
- Do not use a vague
commonmodule as the default destination. - Do not create a vague
easy-postman-coremodule for unrelated request, collection, runtime, and UI concerns. - Do not put Swing code in
foundation. - Do not put request specification models back into
easy-postman-app. - Do not make
easy-postman-request-coredepend on Swing, OkHttp, app service/panel code, or plugin runtime. - Do not put collection core models or Postman collection parsing back into
easy-postman-app. - Do not make
easy-postman-collection-coredepend on Swing, OkHttp, app service/panel/runtime code, platform, plugin runtime, or IOC. - Do not make HTTP runtime/service classes depend directly on Swing/panel or app
SettingManager; adapt UI through neutral sinks/dispatchers and settings throughHttpRuntimeSettingsProviderso Swing, CLI tests, and future JavaFX hosts can provide separate implementations. - Do not put UI view-state, importer scratch DTOs, script snippets, functional runner rows/results, stream message types, certificate settings rows, or history records back into
easy-postman-app/src/main/java/com/laker/postman/model. - Do not put plugin service contracts in
foundation. - Do not put shared reusable UI components directly in
app. - Do not make shared UI components depend on app-owned message bundles, icons, editor themes, or other app resources.
- Do not duplicate generic short labels in
ui-messages*or plugin message bundles whenCommonMessageKeysalready owns them. - Do not make plugins depend on
easy-postman-app. - Do not introduce new app-local color/font/button conventions before checking
easy-postman-ui. - Do not duplicate same-named
icons/*.svgresources betweeneasy-postman-appandeasy-postman-ui; shared control icons belong inui, app/domain icons stay with their owning app/plugin module. If a plugin references an icon, it must be plugin-owned or UI-owned.
Verification
For module-boundary changes, run:
mvn -q -pl easy-postman-app -am -Dtest=ModuleArchitectureBoundaryTest -Dsurefire.failIfNoSpecifiedTests=false test
mvn -q -pl easy-postman-plugin-runtime -am -Dtest=PluginRuntimeTest -Dsurefire.failIfNoSpecifiedTests=false test
mvn -q -pl easy-postman-app -am -Dtest=PluginUpdateCheckerTest -Dsurefire.failIfNoSpecifiedTests=false test
mvn -q -pl easy-postman-platform -am -Dtest=UpdateSourceSelectorTest,PlatformDownloadUrlResolverTest,AppReleaseSelectorTest -Dsurefire.failIfNoSpecifiedTests=false test
mvn -q -DskipTests compile