@chill-sharp/chill-cli 1.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Chill CLI
2
+
3
+ Create a ChillSharp workspace that is ready for your preferred coding agent.
4
+
5
+ ```bash
6
+ npm install -g @chill-sharp/chill-cli
7
+ chill new my-data-project
8
+ cd my-data-project
9
+ ```
10
+
11
+ `chill new` creates the project directory and installs the maintained ChillSharp agent skills in `.agents/skills`. It also adds `AGENTS.md` with instructions that agent tools can follow while developing the project.
12
+
13
+ The command uses only Node.js standard-library APIs, so it works on Linux, macOS, and Windows with Node.js 20 or later.
14
+
15
+ ## Command
16
+
17
+ ```text
18
+ chill new <project-name>
19
+ ```
20
+
21
+ Project names use lowercase letters, digits, and hyphens. The command refuses to overwrite an existing directory.
package/bin/chill.mjs ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const packageDirectory = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
8
+ const packageManifest = JSON.parse(readFileSync(path.join(packageDirectory, 'package.json'), 'utf8'));
9
+ const [command, projectName] = process.argv.slice(2);
10
+
11
+ if (command === 'new') {
12
+ createProject(projectName);
13
+ } else if (command === '--help' || command === '-h' || command === 'help' || !command) {
14
+ printUsage();
15
+ process.exit(command ? 0 : 1);
16
+ } else if (command === '--version' || command === '-v') {
17
+ console.log(packageManifest.version);
18
+ } else {
19
+ console.error(`Unknown command: ${command}`);
20
+ printUsage();
21
+ process.exit(1);
22
+ }
23
+
24
+ function createProject(name) {
25
+ if (!name) {
26
+ console.error('A project name is required.');
27
+ printUsage();
28
+ process.exit(1);
29
+ }
30
+
31
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(name)) {
32
+ console.error('Project names must use lowercase letters, digits, and hyphens only.');
33
+ process.exit(1);
34
+ }
35
+
36
+ const destination = path.resolve(process.cwd(), name);
37
+ if (existsSync(destination)) {
38
+ console.error(`Cannot create '${name}': '${destination}' already exists.`);
39
+ process.exit(1);
40
+ }
41
+
42
+ mkdirSync(destination);
43
+ cpSync(path.join(packageDirectory, 'skills'), path.join(destination, '.agents', 'skills'), { recursive: true });
44
+ writeFileSync(path.join(destination, 'AGENTS.md'), projectInstructions(name));
45
+ writeFileSync(path.join(destination, 'README.md'), projectReadme(name));
46
+ writeFileSync(path.join(destination, '.gitignore'), '.DS_Store\nThumbs.db\n.env\n');
47
+
48
+ console.log(`Created ${name}.`);
49
+ console.log('Agent skills were added to .agents/skills.');
50
+ console.log('Next steps:');
51
+ console.log(` cd ${name}`);
52
+ console.log(' Open this folder in your coding agent and describe the first useful outcome.');
53
+ }
54
+
55
+ function projectInstructions(name) {
56
+ return `# ${name}\n\nThis project is prepared for ChillSharp development with a coding agent.\n\nBefore changing ChillSharp code, inspect the relevant skill in \`.agents/skills\`. Use the project\'s existing conventions and keep implementation work focused on the requested outcome.\n\nFor a new ChillSharp backend, start by describing the users, data, and first workflow. The agent can then use the included model, registration, permissions, i18n, menu, plugin, and MCP guidance as needed.\n`;
57
+ }
58
+
59
+ function projectReadme(name) {
60
+ return `# ${name}\n\nA ChillSharp project workspace prepared for coding agents.\n\n## Start building\n\nOpen this folder with your coding agent and describe the first outcome you want to deliver. The agent guidance lives in [\`.agents/skills\`](.agents/skills).\n\nFor example:\n\n> Build a service directory for our nonprofit. Visitors should be able to find local support services, while staff can securely manage the underlying data.\n\n## Included guidance\n\nThe workspace contains ChillSharp skills for model preparation, registration, permissions, localized text, menus, client plugins, current-user preferences, documentation, and MCP.\n`;
61
+ }
62
+
63
+ function printUsage() {
64
+ console.log('Usage: chill new <project-name>');
65
+ console.log('');
66
+ console.log('Commands:');
67
+ console.log(' new <project-name> Create an agent-ready ChillSharp workspace.');
68
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@chill-sharp/chill-cli",
3
+ "version": "1.1.16",
4
+ "description": "Start a ChillSharp project with agent-ready guidance.",
5
+ "license": "AGPL-3.0-or-later",
6
+ "type": "module",
7
+ "bin": {
8
+ "chill": "./bin/chill.mjs"
9
+ },
10
+ "files": [
11
+ "bin",
12
+ "skills",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "node scripts/sync-skills.mjs && node --check bin/chill.mjs",
17
+ "check": "node --check bin/chill.mjs",
18
+ "test": "node --test"
19
+ },
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "keywords": [
24
+ "chillsharp",
25
+ "cli",
26
+ "coding-agent",
27
+ "starter"
28
+ ],
29
+ "author": "Andrea Piovesan",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/e-500/chill-sharp.git",
33
+ "directory": "extra/chill-cli"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/e-500/chill-sharp/issues"
37
+ },
38
+ "homepage": "https://github.com/e-500/chill-sharp#readme",
39
+ "publishConfig": {
40
+ "access": "public"
41
+ }
42
+ }
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: chillsharp-current-user-preferences
3
+ description: Configure, expose, and consume ChillSharp.Auth's cached current-user culture, time zone, date-format, number-format, and theme preferences in server logic and UI clients.
4
+ ---
5
+
6
+ # ChillSharp Current User Preferences
7
+
8
+ Use this skill when a ChillSharp feature needs the authenticated user's display culture, time zone, date format, number format, or preferred theme. It covers server-side lifecycle hooks and UI/client consumption of the authoritative `AuthUser` preferences. Do not use it for browser-only preferences unrelated to `AuthUser`.
9
+
10
+ ## Model
11
+
12
+ `ChillUserPreferences` is an immutable snapshot with `DisplayCultureName`, `DisplayTimeZone`, `DisplayDateFormat`, `DisplayNumberFormat`, and `PreferredTheme`. Entity hooks read it synchronously through:
13
+
14
+ ```csharp
15
+ var preferences = context.GetCurrentUserPreferences();
16
+ ```
17
+
18
+ Never load `AuthUser` from an `OnCreate`, `OnUpdate`, or other lifecycle hook merely to obtain these values.
19
+
20
+ ## Auth integration
21
+
22
+ `AddChillAuthApi` registers `IChillAuthUserPreferencesAccessor` and the singleton `IChillAuthUserPreferencesCache`. Login and token refresh warm the snapshot; `ChillAuthService` refreshes it after an `AuthUser` save and removes it for deleted or renamed external identities.
23
+
24
+ For a custom host DbContext, inject the scoped accessor and implement the two `IChillContext` methods below. Keep the accessor optional only when the context must also be constructible outside DI, such as for migrations or tests.
25
+
26
+ ```csharp
27
+ private readonly IChillAuthUserPreferencesAccessor? _userPreferencesAccessor;
28
+
29
+ public ChillUserPreferences GetCurrentUserPreferences() =>
30
+ _userPreferencesAccessor?.Current ?? ChillUserPreferences.Empty;
31
+
32
+ public string GetDefaultUserCultureName()
33
+ {
34
+ var cultureName = GetCurrentUserPreferences().DisplayCultureName;
35
+ return string.IsNullOrWhiteSpace(cultureName) ? GetPrimaryCultureName() : cultureName;
36
+ }
37
+ ```
38
+
39
+ The accessor is cache-only: when there is no authenticated principal or no warmed snapshot, it returns `ChillUserPreferences.Empty`. Do not add a fallback database query to lifecycle hooks.
40
+
41
+ ## API and client use
42
+
43
+ The authenticated endpoint `GET /api/chill-auth/current-user-preferences` returns the same `ChillUserPreferences` snapshot as JSON:
44
+
45
+ ```json
46
+ {
47
+ "displayCultureName": "it-IT",
48
+ "displayTimeZone": "Europe/Rome",
49
+ "displayDateFormat": "dd/MM/yyyy",
50
+ "displayNumberFormat": "N2",
51
+ "preferredTheme": "cini"
52
+ }
53
+ ```
54
+
55
+ Use this endpoint after authentication and when restoring a session; do not infer the active display culture or time zone from the browser, operating system, token claims, or auth-management user endpoints. The C#, Python, TypeScript, Angular, Vue, and React clients expose it as `GetCurrentUserPreferences`, `get_current_user_preferences`, or `getCurrentUserPreferences`; the Vue and React packages also provide `useCurrentUserPreferences`.
56
+
57
+ In Angular UI Core, inject `ChillService` and read its `userPreferences` signal (or its `displayCultureName`, `displayTimeZone`, `displayDateFormat`, `displayNumberFormat`, and `preferredTheme` projections). Use these values to select UI language, format and parse dates and numbers, convert UTC timestamps, and select the client theme. The backend treats `PreferredTheme` as an opaque string. UI Core defaults unauthenticated users to browser `prefers-color-scheme` light/dark and clients register extra selectable themes with `provideChillSharpUiCore({ additionalThemes: ['theme-name'] })`.
58
+
59
+ ## Entity use
60
+
61
+ Use `DisplayTimeZone` as an IANA zone identifier only after validating it with the application's time-zone policy. Treat all fields as optional and provide an explicit fallback where one is required.
62
+
63
+ ```csharp
64
+ public override void OnUpdate(IChillContext context)
65
+ {
66
+ var timeZone = context.GetCurrentUserPreferences().DisplayTimeZone;
67
+ // Apply application-specific behavior only when timeZone is available.
68
+ }
69
+ ```
70
+
71
+ For full setup and cache behavior, read [CurrentUserPreferences.md](../../../doc/CurrentUserPreferences.md).
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: chillsharp-documentation
3
+ description: Create or update ChillSharp repository documentation under doc with a mirrored Italian translation and reciprocal language switchers.
4
+ ---
5
+
6
+ # ChillSharp Documentation
7
+
8
+ Use this skill for every Markdown change below `doc/`, including new guides and translated documentation.
9
+
10
+ ## Localization contract
11
+
12
+ - The English source lives at `doc/<relative-path>.md`.
13
+ - Create and maintain its Italian translation at `doc/it/<relative-path>.md`; preserve the same relative directory and filename.
14
+ - Each document must start with its title and then a reciprocal language switcher within the opening section:
15
+ - English: `Versione italiana: [Italiano](<relative link to doc/it/...>)`
16
+ - Italian: `English version: [English](<relative link to doc/...>)`
17
+ - Translate prose, headings, image alt text, and link text for the Italian version. Keep code, commands, identifiers, file paths, URLs, and literal API payload fields unchanged unless their surrounding explanatory prose requires a translation.
18
+ - When an English document changes, apply the equivalent semantic change to its Italian counterpart in the same task. Do not leave a placeholder, an English duplicate, or a stale translation.
19
+
20
+ ## Workflow
21
+
22
+ 1. For a new document, create the English document and its Italian counterpart together.
23
+ 2. Keep internal links valid from both mirrored locations; use relative Markdown links.
24
+ 3. Run `python .agents/skills/chillsharp-documentation/scripts/check_localized_docs.py doc` before handing off documentation changes. Resolve every reported issue.
25
+
26
+ The checker verifies structure and switchers. Review the translation itself for meaning, terminology, and code fidelity.
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env python3
2
+ """Validate the mirrored English/Italian Markdown documentation layout."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import sys
7
+ import re
8
+ from pathlib import Path
9
+
10
+
11
+ def has_switcher(path: Path, label: str, target: Path) -> bool:
12
+ lines = path.read_text(encoding="utf-8").splitlines()
13
+ pattern = re.compile(rf"\[{re.escape(label)}\]\(([^)]+)\)")
14
+ for line in lines[:12]:
15
+ match = pattern.search(line)
16
+ if match and (path.parent / match.group(1)).resolve() == target.resolve():
17
+ return True
18
+ return False
19
+
20
+
21
+ def main() -> int:
22
+ if len(sys.argv) != 2:
23
+ print("Usage: check_localized_docs.py <doc-root>", file=sys.stderr)
24
+ return 2
25
+
26
+ doc_root = Path(sys.argv[1]).resolve()
27
+ italian_root = doc_root / "it"
28
+ if not doc_root.is_dir():
29
+ print(f"Documentation root does not exist: {doc_root}", file=sys.stderr)
30
+ return 2
31
+
32
+ issues: list[str] = []
33
+ english_documents = sorted(
34
+ path for path in doc_root.rglob("*.md") if italian_root not in path.parents
35
+ )
36
+
37
+ for english_path in english_documents:
38
+ relative_path = english_path.relative_to(doc_root)
39
+ italian_path = italian_root / relative_path
40
+ if not italian_path.is_file():
41
+ issues.append(f"Missing Italian translation: it/{relative_path.as_posix()}")
42
+ continue
43
+
44
+ if not has_switcher(english_path, "Italiano", italian_path):
45
+ issues.append(f"Missing or invalid English switcher: {relative_path.as_posix()}")
46
+
47
+ if not has_switcher(italian_path, "English", english_path):
48
+ issues.append(f"Missing or invalid Italian switcher: it/{relative_path.as_posix()}")
49
+
50
+ if italian_root.is_dir():
51
+ for italian_path in sorted(italian_root.rglob("*.md")):
52
+ relative_path = italian_path.relative_to(italian_root)
53
+ if not (doc_root / relative_path).is_file():
54
+ issues.append(f"Italian document has no English source: it/{relative_path.as_posix()}")
55
+
56
+ if issues:
57
+ print("Documentation localization check failed:")
58
+ for issue in issues:
59
+ print(f"- {issue}")
60
+ return 1
61
+
62
+ print(f"Documentation localization check passed for {len(english_documents)} document(s).")
63
+ return 0
64
+
65
+
66
+ if __name__ == "__main__":
67
+ raise SystemExit(main())
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: chillsharp-i18n
3
+ description: Configure ChillSharp localized text storage, culture-aware schema labels, and i18n client lookups.
4
+ ---
5
+
6
+ # ChillSharp Internationalization
7
+
8
+ Use this skill when a host needs persisted localized text or culture-aware schema metadata.
9
+
10
+ The host `DbContext` must implement `IChillI18nDbContext` and call `modelBuilder.AddChillI18nModel()` from `OnModelCreating`. Register the API with `builder.Services.AddChillI18nApi<TContext>()`; the standard endpoints are `GET /api/chill-i18n/text/{labelGuid}/{cultureName}` and `PUT /api/chill-i18n/text`.
11
+
12
+ Keep primary and secondary culture names on `IChillContext`. `PrimaryLanguageLabel` and `SecondaryLanguageLabel` are schema fallbacks, not a replacement for persisted localized text. Test primary, secondary, and unsupported cultures after creating the EF migration.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: chillsharp-menu-json
3
+ description: Configure or repair ChillSharp workspace menu JSON for CRUD tasks, especially ChillType and ChillQuery values.
4
+ ---
5
+
6
+ # ChillSharp Menu JSON Configuration
7
+
8
+ Use this skill when creating or correcting a persisted workspace menu item whose `ComponentName` is `crud` and whose `ComponentConfigurationJson` selects a ChillSharp entity and query.
9
+
10
+ ## Resolve logical ChillTypes from C# namespaces
11
+
12
+ `chillType` and `chillQuery` are logical ChillTypes, not filesystem paths. Derive each value from the declaring C# namespace after removing the application's `IChillContext.GetChillTypePrefix()`.
13
+
14
+ For example, with a prefix of `MyApp` and these declarations:
15
+
16
+ ```csharp
17
+ namespace MyApp.Model;
18
+ public class Item : ChillEntity { }
19
+ public class ItemQuery : ChillQuery { }
20
+ ```
21
+
22
+ use `Model.Item` and `Model.ItemQuery`—not `Query.ItemQuery`, even if `ItemQuery.cs` resides in a `Model/Query` folder.
23
+
24
+ ## CRUD configuration
25
+
26
+ Keep the entity and query aligned, retain any intentional relations, and use valid JSON:
27
+
28
+ ```json
29
+ {
30
+ "chillType": "Model.Item",
31
+ "viewCode": "default",
32
+ "chillQuery": "Model.ItemQuery",
33
+ "relations": []
34
+ }
35
+ ```
36
+
37
+ When repairing an existing menu item, change only the incorrect logical type unless the user requests other configuration changes. Save the menu entry, reopen the task, and confirm that the type-resolution error is gone.
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: chillsharp-plugin-development
3
+ description: Develop client-owned ChillSharp UI plugins and overrides while keeping shared UI behavior upgradeable.
4
+ ---
5
+
6
+ # ChillSharp UI Plugin Development
7
+
8
+ Use this skill for Angular client features that extend a ChillSharp UI client. Keep application-owned code in the client repository and shared behavior in `@chill-sharp/ui-core`.
9
+
10
+ - Add feature routes/components under `src/app/core/plugins` and register routes from `register-client-plugins.ts`.
11
+ - Add provider replacements under `src/app/core/overrides` and return them from `register-client-overrides.ts`.
12
+ - Aggregate client providers through `provideClientTemplateProviders()` in the app bootstrap.
13
+ - Use public package exports; do not deep-import or patch shared package internals.
14
+
15
+ Keep runtime API URLs, tenant settings, branding, and feature flags in client configuration. Test a clean build after registration changes.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: chillsharp_i18n
3
+ description: Configure ChillSharp localized text storage, culture-aware schema labels, and i18n client lookups.
4
+ ---
5
+
6
+ # ChillSharp Internationalization
7
+
8
+ Use this skill when a host needs persisted localized text or culture-aware schema metadata.
9
+
10
+ ## Backend setup
11
+
12
+ The host `DbContext` must implement `IChillI18nDbContext` and call `modelBuilder.AddChillI18nModel()` from `OnModelCreating`. Register the API with `builder.Services.AddChillI18nApi<TContext>()`; the standard endpoints are `GET /api/chill-i18n/text/{labelGuid}/{cultureName}` and `PUT /api/chill-i18n/text`.
13
+
14
+ Keep primary and secondary culture names on `IChillContext`. `PrimaryLanguageLabel` and `SecondaryLanguageLabel` are schema fallbacks; they are not a replacement for persisted localized text.
15
+
16
+ ## Client behavior
17
+
18
+ Use the generated or `ChillSharp.Client` i18n contract to request the desired culture explicitly. Treat a missing translation as a normal fallback case and keep the fallback order consistent with the host context.
19
+
20
+ ## Checks
21
+
22
+ - Verify the context interface, EF model extension, service registration, and migration are all present.
23
+ - Do not put secrets or tenant-specific state in static localization caches.
24
+ - Test both primary and secondary cultures, plus an unsupported culture fallback.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: chillsharp_mcp
3
+ description: Guidance on configuring, enabling, and designing models for ChillSharp Model Context Protocol (MCP) servers.
4
+ ---
5
+
6
+ # ChillSharp MCP Integration
7
+
8
+ This skill guides you on setting up the Model Context Protocol (`ChillSharp.Mcp`) module, enabling MCP on models, and optimizing database models for AI agent consumption.
9
+
10
+ ## 1. Registration in ASP.NET Core
11
+
12
+ The MCP module is registered automatically with `AddChillApi()` if `options.EnableMcpApi` is not disabled.
13
+
14
+ Alternatively, register it directly in `Program.cs`:
15
+ ```csharp
16
+ using ChillSharp.Mcp.Api;
17
+
18
+ builder.Services.AddChillMcpApi<AppDbContext>(options =>
19
+ {
20
+ options.Enabled = true;
21
+ options.RoutePattern = "/api/chill-mcp"; // Default endpoint for MCP clients
22
+ });
23
+ ```
24
+
25
+ Context Requirements:
26
+ - DbContext must implement `IChillContext` and `IChillSchemaDbContext`.
27
+ - Include `modelBuilder.AddChillSchemaModel()` in `OnModelCreating`.
28
+
29
+ ## 2. Exposing Schemas to MCP
30
+
31
+ To expose an entity or query schema to MCP, set `EnableMCP = true` in `[ChillEntity]`:
32
+ ```csharp
33
+ [ChillEntity(
34
+ UniquePropertyKeyString: "4E16F6C0-6B95-4D67-98BC-9F4D0D63EAF1",
35
+ PrimaryLanguageLabel: "Invoice",
36
+ SecondaryLanguageLabel: "Fattura",
37
+ EnableMCP = true,
38
+ MCPDescription = "Customer invoice header. Use it to inspect invoice identity, customer, dates, totals, and payment state.")]
39
+ public class Invoice : ChillEntity
40
+ {
41
+ // ...
42
+ }
43
+ ```
44
+
45
+ A query DTO is visible and executable through MCP only when its target returned entity has `EnableMCP = true`.
46
+
47
+ ## 3. Best Practices for AI/Agent Optimization
48
+
49
+ - **MCPDescription**: Write detailed descriptions at both the entity and property levels (`MCPDescription` attribute property). Agents rely on this to build correct payloads and query filters.
50
+ - **Explain Filters**: In query property descriptions, explicitly describe search behaviors (e.g. contains-style text search, range boundary, exact match). If unspecified, agents assume exact matches.
51
+ - **Reference Types**: Declare relationships clearly using `ReferenceChillTypeQuery` and descriptions.
52
+ - **Keep Queries Focused**: Prefer specialized query types (e.g., `Query.OpenInvoicesQuery`) rather than general catch-all queries with dozens of optional inputs.
53
+ - **OAuth & Auth**: When using protected APIs, MCP endpoints expect bearer authorization (`Authorization: Bearer <access-token>`). The Identity auth module includes built-in OAuth PKCE flow support for ChatGPT/MCP clients.
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: chillsharp_model_preparation
3
+ description: Guidance on preparing and writing EF Core model/entity classes for ChillSharp including attributes, lifecycle hooks, and DbContext setups.
4
+ ---
5
+
6
+ # ChillSharp Model Preparation
7
+
8
+ This skill guides you on preparing a domain model for ChillSharp, mapping CLR classes to Chill entities, implementing `IChillContext` on the DbContext, using lifecycle hooks, and annotating properties.
9
+
10
+ ## 1. Implement `IChillContext`
11
+
12
+ The `DbContext` must implement `IChillContext` to declare prefixes, culture fallback preferences, and audit tracking usernames.
13
+
14
+ ```csharp
15
+ public class AppDbContext : DbContext, IChillContext
16
+ {
17
+ public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
18
+
19
+ public string GetChillTypePrefix() => "MyCompany.MyProduct.Data";
20
+ public string GetPrimaryCultureName() => "en-US";
21
+ public string GetSecondaryCultureName() => "it-IT";
22
+ public string GetCurrentUserName() => Environment.UserName; // Replace with user principal resolved name if using auth
23
+ }
24
+ ```
25
+
26
+ ## 2. ChillEntity Definition & Property Annotation
27
+
28
+ - Always inherit from `ChillSharp.EF.ChillEntity` for exposed entities.
29
+ - Decorate class with `[ChillEntity]` and assign a stable UUID string for `UniquePropertyKeyString`.
30
+ - Decorate exposed properties with `[ChillProperty]` using a stable UUID string.
31
+ - Override `GetLabel(IChillContext)` to return a user-friendly string (e.g. Title, Name, etc.).
32
+
33
+ ```csharp
34
+ using ChillSharp.Annotations;
35
+ using ChillSharp.EF;
36
+ using System.ComponentModel.DataAnnotations;
37
+
38
+ [ChillEntity(
39
+ UniquePropertyKeyString: "4E16F6C0-6B95-4D67-98BC-9F4D0D63EAF1",
40
+ PrimaryLanguageLabel: "Blog",
41
+ SecondaryLanguageLabel: "Blog")]
42
+ public class Blog : ChillEntity
43
+ {
44
+ [Key]
45
+ public override Guid Guid { get; set; }
46
+
47
+ [ChillProperty(
48
+ UniquePropertyKeyString: "50B1BB6C-D794-41E4-A85C-D4F9D7A6FA7E",
49
+ PrimaryLanguageLabel: "Blog title",
50
+ SecondaryLanguageLabel: "Titolo del blog")]
51
+ public string Title { get; set; } = string.Empty;
52
+
53
+ public override string GetLabel(IChillContext context) => Title;
54
+ }
55
+ ```
56
+
57
+ ## 3. Lifecycle Hooks
58
+
59
+ Provide lifecycle hooks inside the entity by overriding virtual methods:
60
+ - `OnCreate(context)`: Called before first save.
61
+ - `OnUpdate(context)`: Called on create and update flows before save.
62
+ - `OnAfterUpdate(context)`: Called after audit fields are updated and saved, safe to override since base is implemented explicitly.
63
+ - `OnDelete(context)`: Called before entity is deleted.
64
+ - `OnAfterDelete(context)`: Called after entity is deleted from DB.
65
+ - `OnSelect(context)`: Called during retrieval.
66
+ - `OnInflate(context)`: Called when rebuilding relation values.
67
+ - `OnAutocomplete(context)`: Override for search suggestion behavior.
68
+
69
+ ## 4. Metadata Schema & Audit Fields
70
+
71
+ - Audit fields: `Checksum`, `LastUpdateUser`, `LastUpdate`, `LastUpdateUtcOffset` are managed automatically.
72
+ - Ensure context implements additional DB interfaces like `IChillSchemaDbContext`, `IChillAuthDbContext`, or `IChillI18nDbContext` and registers them via `modelBuilder.AddChillSchemaModel()`, etc. in `OnModelCreating`.
73
+
74
+ ## 5. Check A Reference Without Loading It
75
+
76
+ For a dependent-side reference navigation backed by an EF Core foreign-key mapping, use `Exist()` on its `ReferenceEntry` when code only needs to know whether the dependent currently has FK values:
77
+
78
+ ```csharp
79
+ var customerExists = context.Entry(order)
80
+ .Reference(x => x.Customer)
81
+ .Exist();
82
+ ```
83
+
84
+ `Exist()` is intentionally singular (not `Exists`). With its default `false` argument it does not load the related entity. `Exist(true)` loads it only when every FK component has a value. This works when the database does not enforce a physical FK constraint, provided EF Core still has a configured relationship and FK properties. It is a presence check for FK values, not proof that a principal row exists: an orphaned value still returns `true`.
85
+
86
+ Read [the reference-existence guide](../../../doc/ReferenceExistence.md) before using this for composite keys, shadow FKs, or legacy databases.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: chillsharp_permissions
3
+ description: Guidance on using, evaluating, and managing the authorization and permission model in ChillSharp.
4
+ ---
5
+
6
+ # ChillSharp Permissions & Authorization
7
+
8
+ This skill explains how ChillSharp's default-deny, hierarchical permission model works and how to utilize the Auth API.
9
+
10
+ ## 1. Subjects and Precedence
11
+
12
+ Permissions can be assigned to **Users** or **Roles**. The precedence of resolution is:
13
+ 1. User property rules
14
+ 2. User entity rules
15
+ 3. User module rules
16
+ 4. Role property rules
17
+ 5. Role entity rules
18
+ 6. Role module rules
19
+ 7. Default Deny
20
+
21
+ ## 2. Resource Hierarchy and Actions
22
+
23
+ The resource hierarchy is evaluated as:
24
+ `Module -> Entity -> Property`
25
+
26
+ - **Entity Actions**: `Query`, `Create`, `Update`, `Delete`.
27
+ - **Property Actions**: `See`, `Modify`.
28
+ - Property rules refine an allowed entity operation; they do not replace them.
29
+ - To edit a property, you need entity `Create`/`Update` and property `Modify`.
30
+ - To see a property, you need entity `Query` and property `See`.
31
+
32
+ ## 3. Configuration & Enforcement
33
+
34
+ - The system uses a **default-deny** posture. If no rule allows access, it is blocked.
35
+ - Define permission rules via `AuthPermissionRule` entries.
36
+ - Server-side validation automatically executes authorization rules during CRUD actions.
37
+ - Clients can fetch user permissions via `/api/chill-auth/get-permissions` and evaluate access rules locally.
38
+
39
+ ## 4. API Endpoints
40
+
41
+ Privileged users with `CanManagePermissions` can manage ACL/auth settings via:
42
+ - `GET chill-auth/get-user-list`
43
+ - `GET chill-auth/get-user`
44
+ - `POST chill-auth/set-user` (updates roles & user-specific permissions incrementally)
45
+ - `GET chill-auth/get-role-list`
46
+ - `GET chill-auth/get-role`
47
+ - `POST chill-auth/set-role` (updates role permissions & user-role assignments incrementally)
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: chillsharp_plugin_development
3
+ description: Develop client-owned ChillSharp UI plugins and overrides while keeping shared UI behavior upgradeable.
4
+ ---
5
+
6
+ # ChillSharp UI Plugin Development
7
+
8
+ Use this skill for Angular client features that extend a ChillSharp UI client. Keep application-owned code in the client repository and shared behavior in `@chill-sharp/ui-core`.
9
+
10
+ ## Extension boundaries
11
+
12
+ - Add feature routes and route-owned components under `src/app/core/plugins`.
13
+ - Register them from `register-client-plugins.ts`.
14
+ - Add provider replacements under `src/app/core/overrides` and return them from `register-client-overrides.ts`.
15
+ - Aggregate client providers through `provideClientTemplateProviders()` in the app bootstrap.
16
+
17
+ Plugins should consume public exports from `@chill-sharp/ui-core`; do not deep-import package internals or edit copied shared implementation.
18
+
19
+ ## Plugin checklist
20
+
21
+ - Define a stable route and lazy-load large features where appropriate.
22
+ - Keep branding, feature flags, runtime API URLs, and tenant settings in the client-owned config layer.
23
+ - Add a focused README when a plugin has registration, permission, or deployment assumptions.
24
+ - Test a clean build after changing routes/providers and verify the plugin works with the current local package archives.
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: chillsharp_registration
3
+ description: Guidance on registering ChillSharp API, DbContext modules, schema services, auth, and i18n configurations in an ASP.NET Core application.
4
+ ---
5
+
6
+ # Registering a ChillSharp Context
7
+
8
+ This skill describes how to register and configure ChillSharp modules in an ASP.NET Core application.
9
+
10
+ ## 1. DbContext Configuration
11
+
12
+ In your `DbContext` class:
13
+ - Implement `IChillContext` (and optionally `IChillSchemaDbContext`, `IChillAuthDbContext`, `IChillI18nDbContext`).
14
+ - Register internal ChillSharp models in `OnModelCreating(ModelBuilder modelBuilder)` using extension methods:
15
+ - `modelBuilder.AddChillSchemaModel()`
16
+ - `modelBuilder.AddChillAuthModel()`
17
+ - `modelBuilder.AddChillI18nModel()`
18
+
19
+ ## 2. Core API Registration
20
+
21
+ In `Program.cs`:
22
+ ```csharp
23
+ using ChillSharp.Api;
24
+ using Microsoft.EntityFrameworkCore;
25
+
26
+ var builder = WebApplication.CreateBuilder(args);
27
+
28
+ builder.Services.AddDbContext<AppDbContext>(options =>
29
+ options.UseSqlite("Data Source=app.db"));
30
+
31
+ // Register Core Chill API
32
+ builder.Services.AddChillApi<AppDbContext>();
33
+
34
+ var app = builder.Build();
35
+ app.MapChillApi();
36
+ app.Run();
37
+ ```
38
+
39
+ ## 3. Protecting the API
40
+
41
+ If using auth:
42
+ ```csharp
43
+ builder.Services.AddChillApi<AppDbContext>(options =>
44
+ {
45
+ options.ProtectedApi = true;
46
+ });
47
+
48
+ // Middleware setup
49
+ app.UseAuthentication();
50
+ app.UseAuthorization();
51
+ app.MapChillApi();
52
+ ```
53
+
54
+ ## 4. Registering Modules
55
+
56
+ - **Schema Services**:
57
+ ```csharp
58
+ using ChillSharp.Schema;
59
+ builder.Services.AddChillSchema<AppDbContext>();
60
+ ```
61
+ - **Auth Services**:
62
+ ```csharp
63
+ using ChillSharp.Auth.Api;
64
+ builder.Services.AddChillAuthApi<AppDbContext>();
65
+ ```
66
+ - **ASP.NET Core Identity Integration**:
67
+ ```csharp
68
+ using ChillSharp.Auth;
69
+ using ChillSharp.Auth.Api;
70
+ using Microsoft.AspNetCore.Identity;
71
+
72
+ builder.Services.AddIdentityCore<IdentityUser>()
73
+ .AddEntityFrameworkStores<AppDbContext>()
74
+ .AddSignInManager()
75
+ .AddDefaultTokenProviders();
76
+
77
+ builder.Services.AddAuthentication(ChillAuthIdentityDefaults.AuthenticationScheme)
78
+ .AddChillAuthBearer();
79
+ builder.Services.AddAuthorization();
80
+
81
+ // Combined registration
82
+ builder.Services.AddChillApi<AppDbContext, IdentityUser>();
83
+ ```
84
+ - **I18n Localized Text Services**:
85
+ ```csharp
86
+ using ChillSharp.I18n.Api;
87
+ builder.Services.AddChillI18nApi<AppDbContext>();
88
+ ```
89
+
90
+ ## 5. Startup Order Flow
91
+ 1. Register DbContext.
92
+ 2. Register Identity, Authentication, and Authorization.
93
+ 3. Register Chill API (`AddChillApi`).
94
+ 4. Register optional ChillSharp modules (Schema, Auth, I18n).
95
+ 5. Build application, apply middleware (`UseAuthentication`, `UseAuthorization`).
96
+ 6. Call `MapChillApi()`.
97
+ 7. Configure OpenAPI/Swagger for client generation if required.