Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
3e17cb6
chore: Switch all auth requests to use game_api_key as key param
kirre-bylund Feb 26, 2026
e6c0517
fix: Obfuscate game api key
kirre-bylund Mar 2, 2026
ca17561
fix: Remove references to live env (and also stage env)
kirre-bylund Feb 26, 2026
0d444c2
fixes after review
kirre-bylund Mar 6, 2026
6edfa8c
fixes after rebase
kirre-bylund Mar 6, 2026
d5f5682
docs: add Unity SDK architecture + coding agent guardrails
kirre-bylund Feb 23, 2026
6df8b84
docs: move agent docs under .github/instructions
kirre-bylund Feb 24, 2026
8bc4220
docs: add Copilot instruction set
kirre-bylund Feb 24, 2026
d39bae3
PR Fixes
kirre-bylund Feb 25, 2026
9457f4a
ci: add Compile Check workflow and local verification scripts
kirre-bylund Mar 3, 2026
d91ca68
ci: address PR review comments on verification scripts and workflow
Copilot Mar 3, 2026
de54f0f
ci: Add copilot/ branch builds
kirre-bylund Mar 3, 2026
5b0f143
Add Issue Tracking & Lifecycle section to copilot-instructions.md
Copilot Mar 6, 2026
f95e8d0
Move Issue Tracking details to implementation-lifecycle.md, keep copi…
Copilot Mar 6, 2026
ef0c59b
Add .github/PULL_REQUEST_TEMPLATE.md
Copilot Mar 6, 2026
6b64427
feat: Add support to copilot for testing and debugging
kirre-bylund Mar 6, 2026
c5bcdb5
feat: Add RefundByEntitlementIds endpoint (POST /game/refund/v1)
Copilot Mar 6, 2026
b83b460
fix: Convert action/kind/type string fields to enums in refund DTOs
Copilot Mar 6, 2026
ce64b20
feat: Add async purchase support (issue lootlocker/index#1369)
kirre-bylund Mar 6, 2026
fa6eabf
fix: address Copilot review comments
kirre-bylund Mar 6, 2026
df6d217
fix(ci): pre-build go backend binary before healthcheck
ladydascalie Mar 12, 2026
a5972ac
fix(ci): use slim devenv profile to reduce resource pressure
ladydascalie Mar 12, 2026
f081528
fix(ci): update cleanup step to match pre-built binary process name
ladydascalie Mar 12, 2026
5c54a50
ci: Set target environment to local if localhost is specified as the …
kirre-bylund Mar 12, 2026
799dc39
Modify conditions for integration tests and environment setup
kirre-bylund Mar 12, 2026
af1136b
Enable editor-smoke-test conditionally for integration tests
kirre-bylund Mar 12, 2026
1aab264
feat: add metadata support to simplified inventory listing (task-1402)
kirre-bylund Mar 10, 2026
0207801
feat: fix metadata request body shape and update response fields (tas…
kirre-bylund Mar 12, 2026
741fd29
feat: Configure test target user info in dev settings file
kirre-bylund Mar 9, 2026
d898277
fix: Log clearing in run tests script
kirre-bylund Mar 9, 2026
f875024
fix: Always read admin email and password from command line in tests
kirre-bylund Mar 9, 2026
d751046
ci: Add test util to configure game and credit balance
kirre-bylund Mar 9, 2026
7374674
ci: Add endpoints
kirre-bylund Mar 9, 2026
28fa441
ci: Add test util for currency configuration
kirre-bylund Mar 9, 2026
ba0545a
ci: Add test util for catalog configurations
kirre-bylund Mar 9, 2026
a49546e
ci: Add test for async purchases and refunds
kirre-bylund Mar 9, 2026
a7ed5ff
fix: Address PR review comments
kirre-bylund Mar 13, 2026
e483414
feat: Add streamed response parser to LootLockerJson
kirre-bylund Mar 12, 2026
0fa5a37
scout: Remove unused endpoint for streamed assets
kirre-bylund Mar 12, 2026
25cf806
fix: Properly parse streamed asset instance kv pairs response
kirre-bylund Mar 12, 2026
608e42a
fix: Fixes after review
kirre-bylund Mar 16, 2026
0196b49
feat: Add player_not_in_segment trigger failure reason
kirre-bylund Mar 17, 2026
36ef770
feat: Add support for file configurations
kirre-bylund Feb 5, 2026
290a6d9
chore: Remove explicit LootLocker metions from Logs unless strictly n…
kirre-bylund Feb 5, 2026
67e8834
scout: Remove unused request class EventRequest.cs
kirre-bylund Feb 11, 2026
f64495f
fix: Add fallback file reads to file config reading to succeed at imp…
kirre-bylund Feb 11, 2026
c6114c7
ref: Move classes that cause coupling to general definition classes
kirre-bylund Feb 11, 2026
2aab31e
Fixes after review
kirre-bylund Feb 26, 2026
dae772b
feat: add LL-Request-Id and LL-Retry-Attempt headers to all HTTP requ…
kirre-bylund Mar 16, 2026
b7a6f69
feat: add ll.action_name to broadcast language response
kirre-bylund Mar 17, 2026
9ce2b17
fix: Log raw presence responses in debug
kirre-bylund Mar 17, 2026
4faf71b
feat: Add ability to selectively keep lootlocker logs in viewer
kirre-bylund Mar 17, 2026
c4930e5
Fixes after review
kirre-bylund Mar 19, 2026
4004e16
feat: add Stripe Checkout session endpoint (task-1370)
kirre-bylund Mar 16, 2026
86f149a
fix: rename url to checkout_link and add entitlement_id to stripe che…
Copilot Mar 17, 2026
b27bfa5
fix: Remove item_name from stripe checkout request
kirre-bylund Mar 19, 2026
828c13b
Bump version to 7.2.1
kirre-bylund Mar 19, 2026
45ec15f
meta: Add gitattributes file to strip parts of the repo that should n…
kirre-bylund Mar 25, 2026
2ef7019
meta: Add gitattributes file to strip parts of the repo that should n…
kirre-bylund Mar 25, 2026
c43db4b
meta: disable non integration test workflows
kirre-bylund Mar 16, 2026
0aeff62
ci: Make variable configuration step POSIX compatible
kirre-bylund Mar 16, 2026
ea10643
fix: Make LootLockerTestConfigurationCatalog use regular switch case …
kirre-bylund Mar 16, 2026
c47a40e
ci: Add concurrency grouping to the heavy ci
kirre-bylund Mar 23, 2026
de548a8
fix: Adress compilation failure in LootLockerEncryptionUtilities
kirre-bylund Mar 23, 2026
ecd6ba7
fix: Handle malformed json streams
kirre-bylund Mar 24, 2026
942a96d
fix: Access dataPath at runtime only
kirre-bylund Mar 24, 2026
2906001
ci: Add signing step to ci
kirre-bylund Mar 23, 2026
2939959
ci: Reenable CI flow
kirre-bylund Mar 25, 2026
05cfe2e
fix: Update unity-builder
kirre-bylund Mar 25, 2026
18af875
fix: Properly guard editor only calls
kirre-bylund Mar 25, 2026
682e794
fix: Restructure LootLockerConfig::Get()
kirre-bylund Mar 25, 2026
ecbd027
meta: Add unityci docker version lookup script
kirre-bylund Mar 26, 2026
89d410e
ci: Bump integration test time limit becuase devenv takes long to launch
kirre-bylund Mar 27, 2026
8041d10
ci: Add log upload on smoketest failure
kirre-bylund Mar 27, 2026
cc88fe0
fix: Shore up initialization flows to stop crashes
kirre-bylund Mar 30, 2026
93134d9
ci: Increase timeout for integration tests
kirre-bylund Mar 30, 2026
bedb028
ci: Increase integration test
kirre-bylund Apr 1, 2026
77b7db8
fix: Invoke callbacks when session refresh call fails
kirre-bylund Apr 2, 2026
fc5e2aa
ci: Remove HTTP Execution Queue switch
kirre-bylund Apr 2, 2026
9749eaa
fix: Adress review comments
kirre-bylund Apr 8, 2026
68525f5
ci: Timeout devenv launch and retry if it takes too long
kirre-bylund Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Exclude development/internal files from distributed archives
.github/ export-ignore
.git/ export-ignore
Tests/ export-ignore
Tests.meta export-ignore
.editorconfig export-ignore
.gitignore export-ignore
.gitattributes export-ignore
35 changes: 35 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Tracking issue

<!-- Link the relevant lootlocker/index issue. Use "Closes lootlocker/index#<number>" or a plain link. -->

## Description

<!-- Short summary of what changed and why. -->

## Type of change

- [ ] Bug fix
- [ ] New feature
- [ ] Refactor
- [ ] Docs
- [ ] Chore

## Checklist

- [ ] PR targets `dev` branch (not `main`)
- [ ] Branch follows naming convention (`feat/`, `fix/`, `docs/`, `refactor/`, `chore/`, etc.)
- [ ] Diff is minimal and scoped — no unrelated changes, no drive-by refactors
- [ ] No version bumps or release metadata changes (unless explicitly requested)
- [ ] No new helpers/utilities introduced without first searching for existing ones
- [ ] Compile Check CI workflow passes (or verification has been run locally)
- [ ] Runtime code has no unguarded `UnityEditor` dependencies
- [ ] Editor-only code is placed under `Runtime/Editor/` and/or guarded with `#if UNITY_EDITOR`
- [ ] Tracking issue in `lootlocker/index` is linked and status set to "In Review"

## Testing notes

<!-- Describe how the change was verified (manual steps, automated tests, etc.). -->

## Additional notes

<!-- Anything else the reviewer should know (optional). -->
45 changes: 45 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copilot / Coding Agent instructions (LootLocker Unity SDK)

Follow these rules for any work in this repo:

## Non-negotiables
- Never commit directly to `dev` or `main`.
- PRs must target `dev`.
- Do not tag/publish/create releases.
- Do not bump versions or edit release metadata (for example `package.json` version) unless explicitly asked.
- Keep diffs minimal; do not move/rename files unless explicitly requested.
- Search first to avoid duplicating helpers/utilities.

## Architecture references
- Repo structure + “where do I implement X?”: `.github/instructions/architecture.md`
- Guardrails (agent operating rules): `.github/instructions/guardrails.md`

## Verification (compile & test before PR)
- How to verify changes (local + CI): `.github/instructions/verification.md`
- Cloud agent: push to work branch → wait for **Compile Check** workflow.
- Local: run `.github/scripts/verify-compilation.sh` (Linux/macOS) or `.github\scripts\verify-compilation.ps1` (Windows) after creating `unity-dev-settings.json` from the example:
```json
{
"unity_executable": "<absolute path to Unity binary>",
"test_project_path": ""
}
```

## Conventions & style
- Coding conventions & style guide: `.github/instructions/style-guide.md`
- Patterns cookbook (templates): `.github/instructions/patterns.md`
- Path-specific instructions:
- Public API surface (`Runtime/Game/LootLockerSDKManager.cs`): `.github/instructions/Runtime/Game/LootLockerSDKManager.cs.instructions.md`
- Request implementations (`Runtime/Game/Requests/**`): `.github/instructions/Runtime/Game/Requests.instructions.md`
- PlayMode tests (`Tests/LootLockerTests/PlayMode/**`): `.github/instructions/Tests/LootLockerTests/PlayMode.instructions.md`
- Test utilities (`Tests/LootLockerTestUtils/**`): `.github/instructions/Tests/LootLockerTestUtils.instructions.md`

## Testing
- How to write and run tests: `.github/instructions/testing.md`
- Local: `.github\scripts\run-tests.ps1 -TestCategory LootLockerCIFast`
- Cloud agent: **Actions → Run Tests → Run workflow** (supports `testCategory` and `testFilter` inputs).
- How to use tests for debugging (temporary debug tests): `.github/instructions/debugging.md`
- Use `Category("LootLockerDebug")` for temporary debug tests; **always delete before committing**.

## Issue Tracking & Lifecycle
- Full lifecycle rules (status updates, PR linking, DoD): `.github/instructions/implementation-lifecycle.md`
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
applyTo: "Runtime/Game/LootLockerSDKManager.cs"
---

# Scoped instructions: `LootLockerSDKManager.cs` (public API surface)

- Treat this file as the primary, customer-facing API surface. Preserve backward compatibility.
- Prefer additive changes (new methods/overloads) over breaking changes to existing signatures, default values, namespaces, or behavior.
- Keep API methods thin: route work to existing request implementations under `Runtime/Game/Requests/` (or shared helpers) rather than duplicating endpoint/transport logic here.
- Always place methods in this file in a `#region` block corresponding to their feature set (for example, Authentication, Inventory, etc.) and keep them organized with related methods.
- XML docs are required for any `public` API you add or change. Match the existing doc style in this file, including clear `param` descriptions and any practical usage notes.

## XML doc template (adjust as needed)

```csharp
/// <summary>
/// One-sentence description of what the method does.
///
/// Optional additional details or usage notes.
/// </summary>
/// <param name="forPlayerWithUlid"> Optional : Execute the request for the specified player. If not supplied, the default player will be used. </param>
/// <param name="onComplete"> onComplete Action for handling the response </param>
/// <returns>
/// Return value semantics if this API returns a value. Otherwise omit this tag.
/// </returns>
public static void ExampleMethod(string forPlayerWithUlid, Action<LootLockerExampleResponse> onComplete)
{
// Keep facade thin; validate input early; call onComplete once on all paths.
}
```
- If a method takes a player selector, follow the existing `forPlayerWithUlid` convention (optional when appropriate; don’t invent new parameter names for the same concept).
- For callback-based APIs, call `onComplete` exactly once on all code paths (including validation failures).
- Do not log secrets or raw tokens from this layer. Use `LootLockerLogger` (not `Debug.Log`) and rely on log obfuscation (`LootLockerConfig.current.obfuscateLogs`).
- Use the repo’s JSON wrapper (`LootLockerJson`) and existing response/error helpers; do not introduce new serialization/logging dependencies.
- Keep diffs minimal and localized; avoid unrelated refactors in this large file.
18 changes: 18 additions & 0 deletions .github/instructions/Runtime/Game/Requests.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
applyTo: "Runtime/Game/Requests/**/*.cs"
---

# Scoped instructions: `Runtime/Game/Requests/` (request implementations)

- Follow the established split:
- DTOs/response models in `namespace LootLocker.Requests`.
- Request methods in `namespace LootLocker` inside `public partial class LootLockerAPIManager`.
- Responses should inherit `LootLockerResponse` and use property names that match server JSON (commonly `snake_case`), as seen throughout this folder.
- Validate inputs early. For an unserializable/missing body, return a consistent error response via `LootLockerResponseFactory` and invoke `onComplete` once.
- Serialize request bodies with `LootLockerJson.SerializeObject(...)` (never call Newtonsoft/ZeroDep JSON APIs directly).
- Build endpoints via `LootLockerEndPoints` + `EndPointClass.WithPathParameter(s)`; avoid manual string concatenation for path params.
- For query parameters, prefer `LootLocker.Utilities.HTTP.QueryParamaterBuilder` when available; otherwise ensure values are URL-encoded (for example `WebUtility.UrlEncode`).
- Use the standard transport pattern:
- `LootLockerServerRequest.CallAPI(..., onComplete: (serverResponse) => { LootLockerResponse.Deserialize(onComplete, serverResponse); }, useAuthToken: true/false)`
- Keep `useAuthToken` consistent with the endpoint’s auth requirements and nearby examples. This variable is almost always `true`.
- Keep methods small and consistent with surrounding files; don’t move DTOs or rename existing public types unless explicitly requested.
69 changes: 69 additions & 0 deletions .github/instructions/Tests/LootLockerTestUtils.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
applyTo: "Tests/LootLockerTestUtils/**/*.cs"
---

# Scoped instructions: `Tests/LootLockerTestUtils/` (test configuration utilities)

This folder holds the admin-API client and helpers that tests use to provision and tear down
real LootLocker game configurations. It is **not** test code itself — it is infrastructure
that backs the tests under `Tests/LootLockerTests/PlayMode/`.

## Key classes

| Class / File | Responsibility |
|---|---|
| `LootLockerTestGame` | Creates/deletes a game, exposes helpers for common game setup (enable platforms, create leaderboards, etc.). |
| `LootLockerTestUser` | Gets or signs up a time-scoped admin user so the admin API calls are authenticated. |
| `Auth` | Low-level admin login / signup via the LootLocker admin API. |
| `LootLockerAdminRequest` | Thin wrapper around `LootLockerServerRequest.CallAPI` that injects the `Admin` caller role and handles rate-limit retries. |
| `LootLockerTestConfigurationEndpoints` | Constants for all admin API endpoints used by the utilities. |

## How authentication works

`LootLockerTestUser.GetUserOrSignIn` auto-derives a deterministic email from the current
date (e.g. `unity+ci-testrun+2024-04-17-14h@lootlocker.com`) and the same string as the
password, then attempts login and falls back to signup on a 401. This means test runs
are self-contained and need no pre-provisioned secrets in stage environments.

## Transport pattern

All admin API calls use `LootLockerAdminRequest.Send(...)`, which sets
`callerRole: LootLockerCallerRole.Admin`. Never call `LootLockerServerRequest.CallAPI`
directly from this folder — go through `LootLockerAdminRequest.Send`.

```csharp
LootLockerAdminRequest.Send(endPoint.endPoint, endPoint.httpMethod, json,
onComplete: (serverResponse) =>
{
var response = LootLockerResponse.Deserialize<MyResponse>(serverResponse);
onComplete?.Invoke(response);
}, useAuthToken: true);
```

## Adding a new admin API helper

1. Add the endpoint constant to `LootLockerTestConfigurationEndpoints.cs`.
2. Create a request/response DTO (plain class or `LootLockerResponse` subclass) in the
relevant file, or add a new file for a new domain area.
3. Add a static method to the appropriate class (`LootLockerTestGame`, `LootLockerTestAssets`,
etc.) that:
- Checks `if (string.IsNullOrEmpty(LootLockerConfig.current.adminToken))` first and
invokes `onComplete` with a failed response if not authenticated.
- Uses `LootLockerAdminRequest.Send(...)` for transport.
- Deserializes with `LootLockerResponse.Deserialize<T>(serverResponse)`.
4. Map the requests to the correct endpoint according to the api docs: https://ref.lootlocker.com/admin

## Namespace

All classes in this folder live in `namespace LootLockerTestConfigurationUtils`.

## Conventions

- Keep methods callback-based (`Action<...> onComplete`) to match the async Unity pattern
used by tests (`yield return new WaitUntil(() => done)`).
- Do not reference `LootLockerTests` from this utility layer — the dependency runs one way:
tests depend on utils, not the other way.
- Use `LootLockerJson.SerializeObject(...)` for request body serialization — same as runtime.
- Error paths must always invoke `onComplete` exactly once.
- Endpoint strings that include a game ID placeholder use `#GAMEID#`, which
`LootLockerAdminRequest` replaces automatically from `LootLockerAdminRequest.ActiveGameId`.
Loading
Loading